I'm using GNU/make (linux) to wrap some docker command, I don't use docker everyday so I'll forget the usage soon, one of those wrapper is make serve, it run docker run with php -S (built-in server) as command, it start and listen for connections.
To stop it I should use ^C , I believe (but I'm not sure) the problem to be make intercepting the signal, the make's target fail but the php process (and the docker instance) remain running, I've to manually stop it.
I tried passing --sig-proxy=true and false but with no effect, but I'm running the instance with a pseudo terminal (-t) so this was expected.
I wrote a bash wrapper to echo some message when some signal is trapped (EXIT TERM SIGTERM SIGQUIT KILL SIGKILL) and exec php -S , but I don't see any message.
I'm not sure what happen when ^C is pressed on a running make, if the signal (and what) is propagated only to the forked sh -c, and why that wouldn't work with docker run.
I'd like to know if someone else had this problem and solved or if someone can think of some alternative solution.
edit
Makefile:
all:
.PHONY: docker-build serve
docker-build:
docker build -f Dockerfile -t sigtest:v1 .
serve:
docker run -t --rm sigtest:v1 gosu ubuntu:ubuntu php7.0 -S 0.0.0.0:8081 -t /home/ubuntu
Dockerfile:
FROM ubuntu:16.04
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends php7.0-cli gosu
RUN useradd -ms /bin/bash ubuntu
test with make docker-build and then make serve
2nd edit
I managed to wrap docker run with a shell script (I'm not sure about trap syntax in posix shells, eventually I'll take a look)
make seems to be sending INT the first time and and then EXIT
#!/bin/sh
pid=$$
trap 'trap - INT EXIT; echo " signal received, wait..."; docker stop -t 0 sig${pid}; exit' INT EXIT
docker run --name=sig${pid} "$#"
and then in the Makefile
serve:
-./docker-run.sh -t --rm sigtest:v1 gosu ubuntu:ubuntu php7.0 -S 0.0.0.0:8081 -t /home/ubuntu
I was hoping to not have to name the instances but that's the simplest way I can think of.
The problem is not in using make but in the Signal handling. Here is an article describing it.
As I said before docker-compose manages the whole lifecycle of your services.
Here is a basic example of your app using docker-compose. By make up and make down(including ^C ), so you can start and stop your service.
Makefile:
all:
.PHONY: docker-build serve
build:
docker-compose build
up:
docker-compose up
down:
docker-compose down
docker-compose.yml:
version: '3.3'
services:
my_service:
build: .
ports:
- "8080:8080"
Dockerfile:
FROM ubuntu:16.04
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends php7.0-cli gosu
RUN useradd -ms /bin/bash ubuntu
RUN mkdir -p /home/ubuntu
RUN php7.0 --version
ENTRYPOINT php7.0 -S 0.0.0.0:8080
Related
Is it normal to lose all data, installed applications and created folders inside a container when executing docker-compose stop my_image and docker-compose start my_image?
I'm creating container with docker-compose up --scale my_image=4
update no. 1
my containers have sshd server running in them. When I connect to a container execute touch test.txt I see that the file was created.
However, after executing docker-compose stop my_image and docker-compose start my_image a container is empty and ls -l shows absence of file test.txt
update no. 2
my Dockerfile
FROM oraclelinux:8.5
RUN (yum update -y; \
yum install -y openssh-server openssh-clients initscripts wget passwd tar crontabs unzip; \
yum clean all)
RUN (ssh-keygen -A; \
sed -i 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config; \
sed -i 's/#UsePAM no/UsePAM no/g' /etc/ssh/sshd_config; \
sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config; \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config)
RUN (mkdir -p /root/.ssh/; \
echo "StrictHostKeyChecking=no" > /root/.ssh/config; \
echo "UserKnownHostsFile=/dev/null" >> /root/.ssh/config)
RUN echo "root:oraclelinux" | chpasswd
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 22
my docker-compose
version: '3.9'
services:
my_image:
build:
context: .
dockerfile: Dockerfile
ports:
- 30000-30007:22
when I connect to a container
Execute touch test.txt
Execute docker-compose stop my_image
Execute docker-compose start my_image
Execute ls -l
I see no file test.txt (in fact I see that the folder is empty)
update no. 3
entrypoint.sh
#!/bin/sh
# Start the ssh server
/usr/sbin/sshd -D
# Execute the CMD
exec "$#"
Other details
When containers are all up and running, I choose a container running
on a specific port, say port 30001, then using putty I connect to that specific container,
execute touch test.txt
execute ls -l
I do see that the file was created
I execute docker-compose stop my_image
I execute docker-compose start my_image
I connect via putty to port 30001
I execute ls -l
I see no file (folder is empty)
I try other containers to see if file exists inside one of them, but
I see no file present.
So, after a brutal brute force debugging I realized that I lose data
only when I fail to disconnect from ssh before stopping / restarting
container. When I do disconnect data does not disappear after stopping / restarting
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.
i am trying write a Dockerfile like that
FROM debian:stable
RUN apt-get update
RUN apt-get install -y mariadb-server
EXPOSE 3306
CMD ["mysqld"]
I create the image with
docker build -t debian1 .
And i create the container with
docker run -d --name my_container_debian -i -t debian1
20 seconds after, docker ps -a tells that container is exited. Why? I want the container is up and mariadb running. Thanks. Sorry for the question.
mysqld alone would exit too soon.
If you look at a MySQL server Dockerfile, you will note its ENTRYPOINT is a script docker-entrypoint.sh which will exec mysqld in foreground.
exec "$#"
I am a newbie to docker and trying to understand how to create dockerfiles.
While attempting the same I created this sample file
FROM debian
RUN apt-get update && apt-get upgrade -y
RUN apt-get install apache2 -y
COPY ./index.html /etc/www/html/
CMD service apache2 start && /bin/bash
The CMD part has always confused me and I am using the /bin/bash mostly because I read somewhere that we need to make sure that there is some running command in the Docker Image when we are bringing it up. I use this to run the image :-
docker run -t -p 5000:8080 --name myfinal 912ccd578eae
where I'm using the id of the image built. As you can see, I'm a novice and even the minutest of details would help.
The usual CMD for apache2 should be
CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]
That way, you don't have to use the "bash" trick to keep a foreground process running.
And any exit signal will impact correctly the apache2 process, not the bash one.
No need for ENTRYPOINT here: Docker maintains a default entrypoint, /bin/sh.
So this (with CMD) is the same as:
/bin/sh -c “apachectl -D FOREGROUND”
I am having a weird problem.
I am not able to ssh to docker container having ip address 172.17.0.61.
I am getting following error:
$ ssh 172.17.0.61
ssh: connect to host 172.17.0.61 port 22: Connection refused
My Dockerfile does contain openssh-server installation step:
RUN apt-get -y install curl runit openssh-server
And also step to start ssh:
RUN service ssh start
What could be the issue?
When I enter into container using nsenter and start ssh service then I am able to ssh. But while creating container ssh-server doesn't seems to start.
What should I do?
When building a Dockerfile you would create an image. But you can't create an image with an already running ssh daemon or any running service else. First if you create a running container out of the image you can start services inside. E.g. by appending the start instruction to the docker run command:
sudo docker run -d mysshserver service ssh start
You can define a default command for your docker image with CMD. Here is an example Dockerfile:
FROM ubuntu:14.04.1
MAINTAINER Thomas Steinbach
EXPOSE 22
RUN apt-get install -y openssh-server
CMD service ssh start && while true; do sleep 3000; done
You can build an run this image with the following two commands:
sudo docker build -t sshtest .
sudo docker run -d -P --name ssht sshtest
Now you can connect to this container via ssh. Note that in the example Dockerfile no user and no login was created. This image is just for example and you can start an ssh connection to it, but not login.
In my opinion there is a better approach:
Dockerfile
FROM ubuntu:14.04.1
EXPOSE 22
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
RUN apt-get install -y openssh-server
ENTRYPOINT ["sh", "/docker-entrypoint.sh"]
# THIS PART WILL BE REPLACED IF YOU PASS SOME OTHER COMMAND TO docker RUN
CMD while true; do echo "default arg" && sleep 1; done
docker-entrypoint.sh
#!/bin/bash
service ssh restart
exec "$#"
Build command
docker build -t sshtest .
The benefit of this approach is that your ssh daemon will always start when you use docker run, but you can also specify optional arguments e.g.:
docker run sshtest will print default arg every 1 second
whether docker run sshtest sh -c 'while true; do echo "passed arg" && sleep 3; done' will print passed arg every 3 seconds
I had the same problem.
Luckily I could solve it by checking kenorb answer and adapting it to my Dockerfile:
https://stackoverflow.com/a/61738823/4058295
It's worth a try :)