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?

Answers


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.

I wrote about this in this blog post, but you have a really nice article here detailing how and why using supervisor in Docker.

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.


Need Your Help

dyld: Library not loaded ... Reason: Image not found

macos dylib dyld otool install-name-tool

When trying to run an executable I've been sent in Mac OS X, I get the following error

How can i parse H264 file and frames

c++ c visual-c++ h.264

An H264 file is a stream of NAL (Network Abstraction Layer) units, each encoding a frame (I, B, or P). What is the best way to parse this file and to extract sizes and detect ends of each NAL unit ...