15

Let's say I have two Dockerfiles that I use to create images with respective tags:

Dockerfile.A:

FROM some-image

...
EXPOSE 9000

ENTRYPOINT ["some-script.sh"]

and

Dockerfile.B:

FROM A 

...

When I run the image B, does the container also expose the port that I defined in Dockerfile.A, and run the entrypoint script defined there?

More generally, which instructions are inherited from base Dockerfiles, apart from the file system layers?

Richard Kiefer
  • 1,814
  • 2
  • 23
  • 42
  • The general rule of thumb is this , everything is read from the base image ( something like a read-only content source ) and copied into the child image and it will also execute your run/add/copy… operations on the data in the child image , the caveat being that docker will honor the first entry point it encounters in this case it will hit the entry point of the base image. – Soumen Mukherjee Aug 20 '19 at 16:21
  • 1
    `EXPOSE` is purely documentary. It has no (software) effect in `A` and none in `B`. `FROM` references a container image and this is effectively just a zipped filesystem. That's all that's pulled. One piece of functionality you may be interested in is multi-stage builds. The inheritance is (I think) almost the same with the exception of being able to reference A's filesystem directly from B. – DazWilkin Aug 20 '19 at 16:23

3 Answers3

14

These instruction are inherited from the base image along with system files.

EXPOSE

If the base image mentioned these EXPOSE 8080 9090 ports in Dockerfile, then the extend Dockerfile do not to need to expose these port. But there is a difference between exposing and publish.

ENV

If the base image has some ENV like test-a=abc then extended image will have these ENVs.

WorkingDir

If the base image have set "WorkingDir": "/root", then extended iamge will have working direcotry /root

MAINTAINER

MAINTAINER adiii extended image will have the same author if not overide.

Labels

The extended image will have the same label as the base image

onbuild

Designed to run by extended image.

ENTRYPOINT

Same entrypoint as in the base image, unless you overwrite it.

CMD

The extended image has the same CMD as the base image, as long as you do not overwrite the entrypoint instruction, see below.

You can try it.

Dockerfile A

FROM node:8.16
MAINTAINER adiii
LABEL key=test
EXPOSE 8080 9090
ENV test-a=abc
WORKDIR /root
ENTRYPOINT /root
CMD ["npm", "run", "start"]

Now build docker image B

Dockerfile B

FROM a

docker build -t b . Inspect the image b docker inspect b:latest you will see the above instruction iherited from the base image, because Dockerfile B did not overwrite the entrypoint instruction.

If the extended image overwrites the entrypoint, the documentation says CMD will reset to an empty value and must be redefined if wanted.

Richard Kiefer
  • 1,814
  • 2
  • 23
  • 42
Adiii
  • 54,482
  • 7
  • 145
  • 148
4

Everything is inherited. For example, if you have

# Dockerfile.B
FROM A

And then you

docker build -t B -f Dockerfile.B .

Then these two commands are all but identical

docker run ... A ...
docker run ... B ...

Similarly, it doesn’t matter if you put a given command at the end for a base Dockerfile.A, or if you start a Dockerfile.B FROM A and then have the same command.

(I think the one exception here is that specifying ENTRYPOINT in a new Dockerfile resets the CMD to an empty array. I don’t think this happens if you put CMD before ENTRYPOINT in the same Dockerfile.)

(Relatedly, you cannot undo a VOLUME declaration in a derived image, which in turn means you can’t create a MySQL or PostgreSQL image with prepopulated data. I think you also can’t undo EXPOSE though that’s less of a concern, since that directive has so little effect.)

David Maze
  • 130,717
  • 29
  • 175
  • 215
1

All Docker instructions are inherited as well, but keep in mind that EXPOSE doesn't actually publish a port since it will be your final running process (defined in the CMD or ENTRYPOINT) that will be responsible to do that.

Keep in mind that some instructions can be overridden, and taking your two Dockerfiles as a base, if on Dockerfile.b you define a new entrypoint (e.g. ["another-script.sh"]), this will be the effective one once you run the container.

prometherion
  • 2,119
  • 11
  • 22
  • You are right that all instructions are inherited. But also all instructions can also be overwritten! Not only some. Also EXPOSE informs the user which ports can then be accessed and mapped on the host. Indeed the program running inside the container is responsible to actually listen to the exposed port. – Mihai Aug 20 '19 at 19:15
  • 1
    Thanks for the overwriting hint. However, note that overwriting the entrypoint clears the `CMD`, see edited answer by Adiii (awaiting review). – Richard Kiefer Aug 22 '19 at 13:57