Create docker image based on separate custom image that accepts command-line arguments

I don’t think I have the right title, but I’m not 100% sure what the correct one would be. I’m attempting to containerize a Python program that I have which can run as either a server or client based on CLI arguments. I was able to do it successfully by saying:

FROM python:3.5
ADD program/ program/
WORKDIR program/
ENTRYPOINT ["python", "program.py"]

which I can then run with docker run -d program server <port> <protocol> (or client) and it works properly.

I run into problems though, when I try to create images based on the previous image.

For example, if I want to create a server specific image, I tried:

FROM program
ENTRYPOINT ["server"]

and then my goal would be to run it by saying docker run programServer <port> <protocol>, however when I attempt that I get an executable file not found in $PATH" error.

Is there something that I’m missing, or are you not able to “daisy-chain” images this way?

Answer

Two remarks:

  1. each image should contain one ENTRYPOINT and/or one CMD (either defined in the Dockerfile or inherited from its parent image);

  2. each ENTRYPOINT line overrides the previous ENTRYPOINT definition (as a Docker container is intended to run one process, called the entrypoint).

So:

  • you should just write ENTRYPOINT ["python", "program.py", "server"] in your second Dockerfile (for the child image);
  • but you can just as well keep ENTRYPOINT ["python", "program.py"] in your first Dockerfile (for the parent image) as this causes no harm, and allows one to address rule 1 above.

But if a parent image is only intended to serve as a base image, never to be run “as is”, and does not yield a natural entrypoint, you might just put a dummy CMD that prints a warning/error, for example, or a shell − see e.g. the Dockerfile for debian:10.

For more details on {ENTRYPOINT, CMD}, see also this SO answer: What is the difference between CMD and ENTRYPOINT in a Dockerfile?