Getting to Know Dockerfile Instructions: Part 3

By Alwyn Botha, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

Part 3 of this tutorial set explores :

  1. Dockerfile RUN
  2. Dockerfile CMD
  3. Dockerfile ENTRYPOINT
  4. Dockerfile VOLUME
  5. Dockerfile ARG

These remaining tutorials will not show docker build output since it adds no value most of the time.

To follow the steps in this tutorial, make sure you have access to an Alibaba Cloud Elastic Compute Service instance with a recent version of Docker already installed. You can refer to this tutorial to learn how to install Docker on your Linux server.

Dockerfile RUN

Reference information :

RUN has 2 forms:

RUN (shell form, the command is run in a shell, which by default is /bin/sh -c)

RUN “executable”, “param1”, “param2”

The RUN instruction will execute its given commands and create the resulting output in a new layer on top of the current image.

RUN is used to create probably the largest part of an image. It runs most of the commands you are used to use at the shell when setting up a server / vps.

Examples :

Let’s create a simple Dockerfile to show the exec and shell form in use.

The exec form does not invoke a command shell. This means that normal shell processing does not happen: environment variable substitution does not happen using the exec form.


Run :

Expected output :

shell form — Note at step 2 shell variable substitution does happen.

exec form — Note at step 3 shell variable substitution does not happen.

Dockerfile CMD

The CMD and ENTRYPOINT instructions deserve a long tutorial dedicated to them.

The exercises here is a mere 5 percent basic introduction to those commands.

Your containers exist to provide a software service to others. CMD and ENTRYPOINT are the way you define exactly what software will run during your container startup. The totality of the functionality of the Linux universe is vast. Unfortunately that means CMD and ENTRYPOINT have to be infinitely powerful ( tinkerable ) to allow ANY use case.

I suggest that you visit AFTER you finished this set of Dockerfile tutorials. Visit the URL of every one of the top 10 downloaded images. Click on any topmost Dockerfile they have listed. Study how they use CMD and ENTRYPOINT. THIS is what will make you a Dockerfile expert: not all the other easy Dockerfile instructions combined: but the insightful use of CMD and ENTRYPOINT.

For extra expert bonus insights and accelerated learning, download all 10/20 ?? those images and run them on your development server. Also override the CMD and ENTRYPOINTs when you use docker run.

Alibaba has a vast set of cloud services software available at

How you merge, combine and connect those in value adding ways determine your success. CMD and ENTRYPOINT is the way to expose the software in Docker containers.

Here follows my day one ( one-liner Dockerfile ) beginner exercises.

Unfortunately there can only be one CMD instruction in a Dockerfile. So we have to use several tiny Dockerfiles to demo CMD differences.


The CMD instruction has three forms:


The exec form is parsed as a JSON array, which means that you must use double-quotes (“) around words not single-quotes (‘).

nano Dockerfile


Expected output

Now CMD using the shell form:


Expected output :

The exec form does not invoke a command shell — implication: no shell variable substitution.

If you want shell processing features then use the shell form: first example below:

CMD /bin/echo $HOME will show your $HOME directory

CMD [ “echo”, “$HOME” ] will ** not ** show your $HOME directory, but $HOME as is.

For exercise, lets use the shell form to display content of $HOME:

Run :

Enter this text:


Expected output:

Its easy to remember: in the Linux shell you use ** /bin/echo $HOME ** to show value of $HOME. It works exactly like that in a Dockerfile using shell syntax of the CMD instruction.

Notice I just use the following to run an image:

The CMD instruction defines the command to be executed when running the image. On the docker run I specified no command to execute: CMD defines that echo must run in this case.

The RUN command is used to build an image. It gets executed at build time.

The CMD instruction does not execute anything at build time, but specifies the command to run at docker run time.

You can override the CMD defined in the Dockerfile. You do this by specifying a command to execute when you run the image. For example, run:

Expected output :

Note that the echo from the CMD in the Dockerfile is not executed. Only the echo text from the docker run command is shown.



ENTRYPOINT has two forms:

An ENTRYPOINT allows you to configure a container that will run as an executable.

For example, the following will start nginx with its default content, listening on port 80:

docker run -i -t — rm -p 80:80 nginx

Unfortunately the example they gave is incorrect: there is no ENTRYPOINT in the official nginx Dockerfile at

The last line of the nginx Dockerfile is

CMD [“nginx”, “-g”, “daemon off;”]

So when you run the previous shown docker run the CMD executes nginx — there is no ENTRYPOINT in that specific Dockerfile.


Let’s create our own mini Dockerfile that contains an actual ENTRYPOINT instruction so you can see it in action. Shell form first.


Its getting annoying to stop and prune the container after every run.

Note I used the — rm option above. That removes the exited container automatically.

To see how — rm works do the docker run again:

Expected output:


Same output. There is no need to cleanup / prune the exited container. Convenient.

Exec form of ENTRYPOINT example:

nano Dockerfile


Expected output :

Dockerfile VOLUME


The VOLUME instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers.

Completely right: The VOLUME instruction creates a mount point with the specified name

Confusing: marks it as holding externally mounted volumes from native host or other containers.

It does not hold any external mounted volumes — it creates a new volume internal to the container.

The term volume in Linux is related to the Logical Volume Manager (LVM) — The VOLUME instruction does not mount any such external volumes.

“marks it as holding externally mounted volumes from native host ** or other containers 88.” There are NO other containers involved in the VOLUME instruction.

The VOLUME instruction creates a mount point and it creates a directory in the Docker managed /var/lib/docker/volumes/

Preparation: It would help if you have no / few volumes on your development server. So run this command to see your current list of volumes.

The shorter the list the better you will able to see / find the volumes we are going to create. My list is empty so this tutorial will show the full list of volumes that exist at any point.

Let’s use the Dockerfile from the official Docker docs and see what happens:

nano Dockerfile


Enter the ls command — see that myvol exists inside the container.

Enter cat myvol/greeting

Expected output :

exit the container.

The docker run command initializes the newly created volume /myvol with any data that exists at the specified location ( the greeting file ) within the base image.

The name /myvol exists only inside this container. That name is available to no other container.

This Dockerfile results in an image that causes docker run to create a new mount point at /myvol and copy the greeting file into the newly created volume.

myvol is the name and mount point of the volume ONLY inside the container.

No other container can refer to the myvol name / mountpoint.

Important: The volume names generated on your computer will be different. Please use YOUR volume names when following this tutorial.

Expected output :


Expected output :

Note the Mountpoint where the data can be found: Run

It shows the greeting file.

If we now stop this container ( since it got run with — rm ), Docker also removes the anonymous volume/s associated with the container when the container is removed.

If you do a

you will notice the volume is gone.

More About anon Volumes

Let’s run our container with /myvol again.

docker volume list should show one anon volume — random volume name

Let’s start 3 other Alpine containers using an anon volume /myvol as well.



Each of our 4 containers have their OWN volume called /myvol — that name is only available to them internally.

Now run

We have been using only anon volumes in this tutorial.


shows 4 containers been deleted.


Shows all 4 volumes still exist.

To delete those volumes you need to run:

answer y at prompt:

Expected output :

Lessons learnt here:

  1. Anon volumes get created using VOL in a Dockerfile.
  2. Anon volumes can also be created via -volume when running a container.
  3. Anon volumes have no friendly name outside of containers — they are anon.
  4. Anon volumes get deleted automatically if you specify — rm when you run a container.
  5. Use docker volume prune to remove all volumes not used by at least one container.

Named volumes are created outside of containers — and have to be deliberately deleted by name — one by one. Use named volumes for long term data.

Named volumes can be mounted and shared by unlimited number of containers.

Docker volumes is a vast topic —

This part of this tutorial only introduced you briefly to anon / anonymous volumes that get created using VOL in a Dockerfile.

There is no way to rename an anon volume — possibly never will be — see

If you want nicely named volumes you will need named volumes.

Other containers must use the long anonymous name if they wish to use this volume. Obviously this ugly long name is not ideal so the preferred way is to created a NAMED volume outside the container. Then all containers can use that easy, descriptive volume name.

Dockerfile LABEL

Images can have an unlimited number of labels. Those labels can be used to describe the image.

You can also use labels to selectively filter only images with a certain label. Let’s see all that in action.



To show all the labels for an image, run

Extracted snippet output from that command:

Also run:

Expected output :

Only images with that demo label got shown.

Note that the docker images command does not have a label column.

Even the docker images command with the ( — format) option does not have any functionality to print the labels.

Very few official images at the official Docker hub use labels.

However you can create vast structures of meta information ( labels ) on all your images. The only other way to select / classify images is via the single TAG it can have.

Dockerfile ARG


The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build command using the — build-arg = flag.

You can include a default value when you define the ARG instruction.

Arguments are normally used to pass things like user names, directory names, software package version numbers, etc to the build.

Let’s create a simple Dockerfile and see ARG in use:

Enter this:


Expected output :

Note how WORKDIR /root/${target_dir} replace the ${target_dir} with dir1 . Step 7 RUN pwd shows … /root/dir1

Step 5 RUN echo ${target_dir} shows dir1 as well.

We can safely assume that step 6 and 7 replace ${target_dir} with dir1 as well.

If you write programs you know how variable substitution works. ARG works exactly the same.

An ARG only exists during build time. It is not an environment variable. PRINTENV at bash shell will not show them — they do not exist in the shell.

This concludes Part 3 of 4: Get to know all the Dockerfile Instructions. Continue reading Part 4 to learn more.


Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store