skip to Main Content

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


  1. 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

    The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.

    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.

    Login or Signup to reply.
  2. You cannot start background services with a RUN command. They are not persisted in the image, and are stopped as soon as the RUN 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.

    docker run -d your-image /service1
    docker run -d your-image /service2
    
    version: '3.8'
    services:
      service1:
        build: .
        command: /service1
      service2:
        build: .
        command: /service2
    

    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.

    Login or Signup to reply.
  3. FYI:

    • Commands passed to RUN are executed only when you build the image by running docker 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search