Docker multiple entrypoints
Say I have the following Dockerfile:
FROM ubuntu RUN apt-get update RUN apt-get install -y apache2 RUN apt-get install -y mongod #pretend this exists EXPOSE 80 ENTRYPOINT ["/usr/sbin/apache2"]
The ENTRYPOINT command makes it so that apache2 starts when the container starts. I want to also be able to start mongod when the the container starts with the command service mongod start. According to the documentation however, there must be only one ENTRYPOINT in a Dockerfile. What would be the correct way to do this then?
As Jared Markell said, if you wan to launch several processes in a docker container, you have to use supervisor. You will have to configure supervisor to tell him to launch your different processes.
Basically, you will want to do something like:
FROM ubuntu RUN apt-get update RUN apt-get install -y apache2 RUN apt-get install -y mongod #pretend this exists RUN apt-get install -y supervisor # Installing supervisord ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf EXPOSE 80 ENTRYPOINT ["/usr/bin/supervisord"]
And add a configuration a file supervisord.conf
[supervisord] nodaemon=true [program:mongodb] command=/etc/mongod/mongo #To adapt, I don't know how to launch your mongodb process [program:apache2] command=/usr/sbin/apache2 -DFOREGROUND
EDIT: As this answer has received quite lot of upvotes, I want to precise as a warning that using Supervisor is not considered as a best practice to run several jobs. Instead, you may be interested in creating several containers for your different processes and managing them through docker compose. In a nutshell, Docker Compose allows you to define in one file all the containers needed for your app and launch them in one single command.
My solution is to throw individual scripts into /opt/run/ and execute them with:
#!/bin/bash LOG=/var/log/all touch $LOG for a in /opt/run/* do $a >> $LOG & done tail -f $LOG
And my entry point is just the location of this script, say it's called /opt/bin/run_all:
ADD 00_sshd /opt/run/ ADD 01_nginx /opt/run/ ADD run_all /opt/bin/ ENTRYPOINT ["/opt/bin/run_all"]
The simple answer is that you should not because it breaks the single responsibility principle: one container, one service. Imagine that you want to spawn additional cloud images of MongoDB because of a sudden workload - why increasing Apache2 instances as well and at a 1:1 ratio? Instead, you should link the boxes and make them speak through TCP. See https://docs.docker.com/userguide/dockerlinks/ for more info.
I was not able to get the usage of && to work. I was able to solve this as described here: https://stackoverflow.com/a/19872810/2971199
So in your case you could do:
RUN echo "/usr/sbin/apache2" >> /etc/bash.bashrc RUN echo "/path/to/mongodb" >> /etc/bash.bashrc ENTRYPOINT ["/bin/bash"]
You may need/want to edit your start commands.
Be careful if you run your Dockerfile more than once, you probably don't want multiple copies of commands appended to your bash.bashrc file. You could use grep and an if statement to make your RUN command idempotent.
I can think of several ways:
- you can write a script to put on the container (ADD) that does all the startup commands, then put that in the ENTRYPOINT
- I think you can put any shell commands on the ENTRYPOINT, so you can do service mongod start && /usr/sbin/apache2
There is an answer in docker docs: https://docs.docker.com/config/containers/multi-service_container/
But in short
If you need to run more than one service within a container, you can accomplish this in a few different ways.
The first one is to run script which mange your process.
The second one is to use process manager like supervisord
You can't specify multiple entry points in a Dockerfile. To run multiple servers in the same docker container you must use a command that will be able to launch your servers. Supervisord has already been cited but I could also recommend multirun, a project of mine which is a lighter alternative.