how to make docker image ssh enabled - docker

We have docker running on one machine
Workstation running on other machine
I want to do bootstrap from workstation on docker container then our image should be ssh enabled
How to make docker image ssh enabled.

Before you add ssh you should see if docker exec will be sufficient for what you need. (doc link)
If you do need SSH, the following Dockerfile should help (copied from Docker docs):
# sshd
#
# VERSION 0.0.2
FROM ubuntu:14.04
MAINTAINER Sven Dowideit <SvenDowideit#docker.com>
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

Using the CMD command in your Dockerfile will indeed enable ssh
CMD ["/usr/sbin/sshd", "-D"]
But there is a huge downside. If you already have a CMD command (that starts MySQL for example), then you are facing a problem not easily resolved in Docker. You can use only one CMD in Dockerfile. But there is a workaround for that, using supervisor. What you do is tell Dockerfile to install Supervisor:
RUN apt-get install -y openssh-server supervisor
Using supervisor, you can start as many processes as you want on container startup. These processes are defined in supervisor.conf file (naming is arbitrary) located in the directory with your Dockerfile. In your Dockerfile you tell Docker to copy this file during building:
ADD supervisor-base.conf /etc/supervisor.conf
Then you tell Docker to start supervisor when container starts (when supervisor starts, supervisor will also start all processes listed in the supervisor.conf file mentioned above).
CMD ["supervisord", "-c", "/etc/supervisor.conf"]
Your supervisor.conf file may look like this:
[supervisord]
nodaemon=true
[program:sshd]
directory=/usr/local/
command=/usr/sbin/sshd -D
autostart=true
autorestart=true
redirect_stderr=true
There is one issue to be careful about. Supervisor needs to start as a root, otherwise it will throw errors. So if your Dockerfile defines an user to start container with (e.g USER jboss), then you should put USER root at the end of your Dockerfile, so that supervisor starts with root. In your supervisor.conf file you simply define a user for each process:
[program:wildfly]
user=jboss
command=/opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0
[program:chef]
user=chef
command=/bin/bash -c chef-2.1/bin/start.sh
Of course, these users need to be pre-defined in your dockerfile. E.g.
RUN groupadd -r -f jboss -g 2000 && useradd -u 2000 -r -g jboss -m -d /opt/jboss -s /sbin/nologin -c "JBoss user" jboss
You can learn more about Supervisor+Docker+SSH in more details in this article.

Notice: this answer promotes a tool I've written.
Some answers here suggest to place an SSH server inside your container. Conceptually running multiple processes in one container is not the right approach (https://docs.docker.com/articles/dockerfile_best-practices/). A more favorable solution is one that involves multiple containers each running their own process/service. Linking them together would result in a coherent application.
I've created a containerized SSH server that you can 'stick' to any running container. This way you can create compositions with every container, without that container even knowing about ssh. The only requirement is that the container has bash.
The following example would start an SSH server attached to a container with name 'sshd-web-server1'.
docker run -ti --name sshd-web-server1 -e CONTAINER=web-server1 -p 2222:22 \
-v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker \
jeroenpeeters/docker-ssh
You connect to the SSH server with your ssh client of choice, just as you normally would.
Be adviced: Docker-SSH is currently still under development, but it does work! Please let me know what you think
For more pointers and documentation see: https://github.com/jeroenpeeters/docker-ssh

You can find prebuilt images with SSH installed, for instance CentOS tutum/centos and Debian tutum/debian
And the Dockerfiles used to build them
https://github.com/tutumcloud/tutum-centos/blob/master/Dockerfile
https://github.com/tutumcloud/tutum-debian/blob/master/Dockerfile

Related

Emacs in Docker container can't connect to MELPA

I'm currently facing the problem of Emacs not being able to connect to MELPA. When researching this problem, I found out that this problem is discussed in many topics. However, every suggested solution I tried didn't work for me, beside that, the way I've set up my Emacs instance makes me think the root of the problem might be somewhere else (not emacs related itself).
So let me explain my setup:
I have a Windows 10 host, and I'm trying to get GUI Emacs for Linux running on that host. I've tried various methods (VMs, Emacs for Windows, ...). Currently I'm trying to run Emacs inside a Docker container with X11 forwarding with XMing on my host.
Docker version on host: Docker version 19.03.2, build 6a30dfc
I'm using this docker container as a base. However I modified the Dockerfile a bit to fit my needs (I should mention that I've never worked with docker before):
FROM alpine:edge
MAINTAINER Daniel Guerra <daniel.guerra69#gmail.com>
ARG authorizedKeys=authorized_keys
RUN apk add --update openssh util-linux dbus ttf-freefont xauth xf86-input-keyboard emacs-x11 bash git sudo\
&& rm -rf /tmp/* /var/cache/apk/*
RUN addgroup alpine \
&& adduser -G alpine -s /bin/bash -D alpine \
&& echo "alpine:alpine" | /usr/sbin/chpasswd \
&& echo "alpine ALL=(ALL) ALL" >> /etc/sudoers
RUN cp -r /etc/ssh /ssh_orig
RUN rm -rf /etc/ssh/*
ADD etc /etc
ADD docker-entrypoint.sh /usr/local/bin
VOLUME ["/etc/ssh"]
RUN mkdir -p /home/alpine/.ssh
ADD $authorizedKeys /home/alpine/.ssh/authorized_keys
RUN mkdir -p /home/alpine/.config
RUN git clone https://github.com/minikN/dotemacs.git /home/alpine/.config/emacs/
RUN mkdir -p /home/alpine/.emacs.d
RUN ln -s /home/alpine/.config/emacs/init.el /home/alpine/.emacs.d/init.el
RUN ln -s /home/alpine/.config/emacs/config.el /home/alpine/.emacs.d/config.el
RUN ln -s /home/alpine/.config/emacs/config.org /home/alpine/.emacs.d/config.org
RUN chown -R alpine:alpine /home/alpine/.emacs.d
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["/usr/sbin/sshd","-D"]
I basically copy my hosts authorized_keys to the container. I do this because I'm using Putty and it's ssh-agent to connect to the machine via SSH.
After that I just copy my emacs config from my GitHub to the container.
You can find the emacs config here.
If I now start the container connect to it via SSH and start emacs, it opens in XMing. However it just hangs (in fact the whole container hangs up), I just see a white screen. Upon restarting the container and running emacs --daemon I can see that it hangs at
alpine-sshdx:~$ emacs --daemon
Contacting host: melpa.org:443
BTW I've checked several mirrors. melpa.org:443 is just the latest try. Also tried both HTTP/HTTPS.
However doing ping 8.8.8.8 works just fine.
I have absolutely no idea what the cause of this is. But I believe it's something in the container.
Would appreciate any help.

Is it possible to run nginx automatically on every startup in a docker container?

I'm new to docker.
I'm setting up nginx server to serve static files inside a docker container. I'd like to enable nginx to start automatically on every startup inside a docker container.
I've tried changing ENTRYPOINT, CMD and crontab when building DockerImage. But these settings to run nginx on every startup works only the first time I "run" a container. When I "stop" the container and "start" it again, nginx does not start automatically inside the container.
I'm looking for a way to start nginx on every startup of a container and my first question is "is it possible to do this?"
My second question is about a container cycle. Given that there are not many discussions on this subject (all discussions are about automatically running a script or sth else at the moment of "run"), I wonder if it is more efficient to "run" and "kill" a container each time than just "stopping" and "starting" a container.
Here are the lines of code I tried for DockerImage (with crontab), which was my first try.
RUN apt-get install -y cron
COPY run_server /etc/cron.d/run_server
RUN chmod 0644 /etc/cron.d/run_server
RUN crontab /etc/cron.d/run_server
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log
run_server is a simple crontab config file which includes:
#reboot service nginx start
Since this was not the solution I was looking for (it worked only when I "ran" a conainer, not "stopped" and "started" a container) I tried with supervisor, too.
RUN apt-get -y install supervisor && \
mkdir -p /var/log/supervisor && \
mkdir -p /etc/supervisor/conf.d
ADD supervisor.conf /etc/supervisor.conf
CMD ["supervisord", "-c", "/etc/supervisor.conf"]
supervisor.confg contains:
[supervisord]
nodaemon=true
[program:run_server]
command=/usr/bin/python3.6 /home/server.py
autostart=true
directory=/home
redirect_stderr=true
But neither of them worked the way I wanted ..
my Dockerfile , container ( CentOS 8 and nginx ) linux mint 19.3 Docker version 19.03.4
# howto: Dockerfile
# CentOS 8 and nginx
# docker build -t centose .
# docker run -it -p 80:80 centose
# curl localhost
FROM centos:latest
# MAINTAINER їван
RUN yum -y install nginx
EXPOSE 80
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
#WORKDIR /usr/sbin/
I would try to update my docker file and enable the nginx service so it will be started during the next reboot.
Here is a couple of different ways:
RUN systemctl enable nginx
RUN service nginx start
Another way would be to add a bootstrap script that starts the service:
#!/bin/bash
sudo service nginx start
tail -f /var/log/nginx/error.log
Make sure the bootstrap.sh is executable i.e sudo chmod +x bootstrap.sh.
Then update your docker file:
COPY boostrap.sh /bin/.
CMD ["bootstrap.sh"]
you can apply that using docker restart policy
you can simply set it when creating the container or updating the created ones
examples: docker run -t -d --restart unless-stopped nginx
to update the created ones: docker update --restart unless-stopped {container ID}

Docker Startup Multiple service is not working

Dockerfile
FROM drupal
RUN apt-get update
RUN apt-get install openssh-server -y
RUN apt-get install -y supervisor
#SS Related Fix : https://github.com/Microsoft/WSL/issues/3621
RUN mkdir -p /run/sshd
# SS Access Configuration
RUN echo "root:Docker!" | chpasswd
#Project Uplaod
RUN rm -rf /var/www/html/*
COPY ./html/ /var/www/html/
# Startup Configuration
COPY servername.conf /etc/apache2/conf-enabled/servername.conf
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord"]
Start Command : docker -D run -p 80:80 -p 2222:22 -it /bin/bash
[supervisord]
nodaemon=true
[program:SSH]
command=/usr/sbin/sshd start
[program:Apache]
command=/etc/init.d/apache2 start
when i jump into Shell and run that command it works but when i start container its not starting up the web server.
As standing in documentation
To start supervisord, run $BINDIR/supervisord. The resulting process
will daemonize itself and detach from the terminal. It keeps an
operations log at $CWD/supervisor.log by default.
You may start the supervisord executable in the foreground by passing
the -n flag on its command line. This is useful to debug startup
problems.
So systemd detach from main process what means for docker that process ended - exit container. To solve your problem you need to change CMD section to
CMD ["/usr/bin/supervisord", "-n"]
When you run
docker -D run -p 80:80 -p 2222:22 -it /bin/bash
The last part of the command, /bin/bash, replaces the CMD in the Dockerfile, so you only get the GNU bash shell. You should remove that part of the line and the standard command from your image will run.
You might consider how much you actually need an interactive shell in your Docker environment. Most application images are set up to run totally on their own without manual setup steps; compare the stock mysql or nginx images, for instance, which don't include any kind of remote login system. Also consider that anyone who can run docker history can now trivially find out your root password, and you have no way to manage the sshd host keys. I'd suggest removing this entire supervisord/sshd system and just packaging your application.

Keeping Docker container alive running Java application

Im having a recurring issue while trying to set up a Docker container so that it stays running.
Here is a sample of the Dockerfile that I am wanting to use:
RUN wget -O /usr/local/nexus-2.11.3-01-bundle.tar.gz http://www.sonatype.org/downloads/nexus-2.11.3-01-bundle.tar.gz
WORKDIR /usr/local
RUN tar xvzf /usr/local/nexus-2.11.3-01-bundle.tar.gz
RUN ln -s nexus-2.11.3-01 nexus
ENV NEXUS_HOME /usr/local/nexus
ENV RUN_AS_USER root
CMD ["/usr/local/nexus/bin/nexus", "start"]
EXPOSE 8081
Basically when I build this, and then run it, the container just dies, and doing a docker ps command returns that there are no running containers.
As far as I know, (please correct me if I'm wrong...) the docker container should stay running so long as theres a process with a pid of 1. Would the usage of the previous commands use PID 1, and if so, how can I force the nexus start command to use it? Or to just keep the container alive...
The contents of a docker logs nexus gives:
****************************************
WARNING - NOT RECOMMENDED TO RUN AS ROOT
****************************************
Starting Nexus OSS...
Started Nexus OSS.
It seems to suggest that Nexus has started, but then again when I do a docker ps, I don't see it running.
If the process running with PID 1 exits, then the container is automatically stopped. You can check on the sonatype/nexus repository here, using the concept of Launcher.
Here is how they are avoiding the container to exit:
...
RUN mkdir -p /opt/sonatype/nexus \
&& curl --fail --silent --location --retry 3 \
https://download.sonatype.com/nexus/professional-bundle/nexus-professional-${NEXUS_VERSION}-bundle.tar.gz \
| gunzip \
| tar x -C /tmp nexus-professional-${NEXUS_VERSION} \
&& mv /tmp/nexus-professional-${NEXUS_VERSION}/* /opt/sonatype/nexus/ \
&& rm -rf /tmp/nexus-professional-${NEXUS_VERSION}
RUN useradd -r -u 200 -m -c "nexus role account" -d ${SONATYPE_WORK} -s /bin/false nexus
...
EXPOSE 8081
WORKDIR /opt/sonatype/nexus
USER nexus
ENV CONTEXT_PATH /
ENV MAX_HEAP 768m
ENV MIN_HEAP 256m
ENV JAVA_OPTS -server -XX:MaxPermSize=192m -Djava.net.preferIPv4Stack=true
ENV LAUNCHER_CONF ./conf/jetty.xml ./conf/jetty-requestlog.xml
CMD java \
-Dnexus-work=${SONATYPE_WORK} -Dnexus-webapp-context-path=${CONTEXT_PATH} \
-Xms${MIN_HEAP} -Xmx${MAX_HEAP} \
-cp 'conf/:lib/*' \
${JAVA_OPTS} \
org.sonatype.nexus.bootstrap.Launcher ${LAUNCHER_CONF}
Since it is an open repository, you can directly refer to their repo, if you like.
A quick guess from the logs is that running /usr/local/nexus/bin/nexus start would start it as a daemon.
That would cause another process to spawn and the one that started the daemon would exit, terminating the container.
One solution is to start the process not as a daemon, but I couldn't find a option to do this in your nexus case.
Another is to use something like supervisord as the CMD to docker. Then make it start your process.

How to SSH into Docker?

I'd like to create the following infrastructure flow:
How can that be achieved using Docker?
Firstly you need to install a SSH server in the images you wish to ssh-into. You can use a base image for all your container with the ssh server installed.
Then you only have to run each container mapping the ssh port (default 22) to one to the host's ports (Remote Server in your image), using -p <hostPort>:<containerPort>. i.e:
docker run -p 52022:22 container1
docker run -p 53022:22 container2
Then, if ports 52022 and 53022 of host's are accessible from outside, you can directly ssh to the containers using the ip of the host (Remote Server) specifying the port in ssh with -p <port>. I.e.:
ssh -p 52022 myuser#RemoteServer --> SSH to container1
ssh -p 53022 myuser#RemoteServer --> SSH to container2
Notice: this answer promotes a tool I've written.
The selected answer here suggests to install an SSH server into every image. Conceptually this is not the right approach (https://docs.docker.com/articles/dockerfile_best-practices/).
I've created a containerized SSH server that you can 'stick' to any running container. This way you can create compositions with every container. The only requirement is that the container has bash.
The following example would start an SSH server exposed on port 2222 of the local machine.
$ docker run -d -p 2222:22 \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
jeroenpeeters/docker-ssh
$ ssh -p 2222 localhost
For more pointers and documentation see: https://github.com/jeroenpeeters/docker-ssh
Not only does this defeat the idea of one process per container, it is also a cumbersome approach when using images from the Docker Hub since they often don't (and shouldn't) contain an SSH server.
These files will successfully open sshd and run service so you can ssh in locally. (you are using cyberduck aren't you?)
Dockerfile
FROM swiftdocker/swift
MAINTAINER Nobody
RUN apt-get update && apt-get -y install openssh-server supervisor
RUN mkdir /var/run/sshd
RUN echo 'root:password' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
EXPOSE 22
CMD ["/usr/bin/supervisord"]
supervisord.conf
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
to build / run start daemon / jump into shell.
docker build -t swift3-ssh .
docker run -p 2222:22 -i -t swift3-ssh
docker ps # find container id
docker exec -i -t <containerid> /bin/bash
I guess it is possible. You just need to install a SSH server in each container and expose a port on the host. The main annoyance would be maintaining/remembering the mapping of port to container.
However, I have to question why you'd want to do this. SSH'ng into containers should be rare enough that it's not a hassle to ssh to the host then use docker exec to get into the container.
Create docker image with openssh-server preinstalled:
Dockerfile
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
Build the image using:
$ docker build -t eg_sshd .
Run a test_sshd container:
$ docker run -d -P --name test_sshd eg_sshd
$ docker port test_sshd 22
0.0.0.0:49154
Ssh to your container:
$ ssh root#192.168.1.2 -p 49154
# The password is ``screencast``.
root#f38c87f2a42d:/#
Source: https://docs.docker.com/engine/examples/running_ssh_service/#build-an-eg_sshd-image
It is a short way but not permanent
first create a container
docker run ..... -p 22022:2222 .....
port 22022 on your host machine will map on 2222, we change the ssh port on container later
, then on your container executing the following commands
apt update && apt install openssh-server # install ssh server
passwd #change root password
in file /etc/ssh/sshd_config change these :
uncomment Port and change it to 2222
Port 2222
uncomment PermitRootLogin to
PermitRootLogin yes
and finally restart ssh server
/etc/init.d/ssh start
you can login to your container now
ssh -p 22022 root#HostIP
Remember : if you restart the container you need to restart ssh server again

Resources