Currently I have a dockerfile that runs two executables using an ampersand:
FROM <Linux base image>
CMD ["bin/sh", "-c", "/service1 & /service2"]
As I am looking to migrate this dockerfile to distroless, I will no longer be able to run this ampersand command, since my new minimal image will no longer have a shell to recognize it. Thus I am looking for alternate ways to ensure I can run both services from the same image.
As an alternative, I am experimenting with doing something like this:
FROM <minimal base image>
RUN /service1
CMD ["/service2"]
Is there any issue with executing /service1 using the RUN command? Is this even possible, given /service1 will be a process running on the container?
Note: I am aware it is not usually recommended to run two services from the same container, but this is to help me better understand RUN and CMD commands. I have read through Dockerfile reference but it is still unclear to me. I have also tested this out locally and the container fails to run, although I do not see logs to confirm this is the reason.
3
Answers
The
RUN
instruction is executed at container build time and the result of the command is saved to the image that is built as a new layer.See the reference here RUN
I would recommend writing a single initialization script that starts your services for you. Since you cannot rely on any distro specific tooling you would need to execute the script with something that you installed earlier in your docker file.
You cannot start background services with a
RUN
command. They are not persisted in the image, and are stopped as soon as theRUN
command completes.What you can do, though, is override the
CMD
when you run the container. Rather than trying to run two processes in a single container, it’s a better practice to run two separate containers with one process each.Since this setup doesn’t require a shell or any other sort of automation in a container, it will also work just fine with a
FROM scratch
or another kind of "distroless" image.Fundamentally a container runs one process (which could launch subprocesses) and when that process completes the container exits. If you want to run two processes in the same container then either one needs to launch the other, or you need some common parent process that can manage the two. That requires you to introduce at least a shell in most cases, which gets away from the spirit of these extremely minimal images.
FYI:
Commands passed to
RUN
are executed only when you build the image by runningdocker build -t ...
Commands passed to
CMD
are executed only when you run a container from that image you built (not executed while building the image).See also
PS: For your specific scenario (for experimental purposes probably) without splitting each executable to a dedicated container, you may also try to
1- Research
supervisord
service which can run & manage multiple services/processes and implement it in your container.2- Call and run the second executable from the first one (if it is possible) as an alternative not recommended solution.