Getting to Know Dockerfile Instructions: Part 2

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.

This tutorial continues to give you practical experience using Dockerfile instructions. 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.

It explores:

  1. Dockerfile HEALTHCHECKs
  2. Dockerfile environment variables — ENV
  3. Dockerfile ports — PORT

Dockerfile HEALTHCHECK

In this section you are going to learn how to use HEALTHCHECK in a Dockerfile.

HEALTHCHECK automate checks the health of your containers on a schedule you specify.

HEALTHCHECK [OPTIONS] CMD command

The options that can appear before CMD are:

For the purposes of this tutorial those durations are VERY long. We want to immediatly test and see the checks work.

Add only this to Dockerfile using

nano Dockerfile

Important: please note the curl -f http://localhost/ health check command will ALWAYS fail in this specific Alpine container: we have no webserver running in the container.

Build the image using

Let’s start up a container to see the result.

After the container starts, you have to execute docker ps -a repeatedly every second ( for 10 seconds ) to see how the health checks progress.

Expected output:

ten seconds later below:

Expected output

(health: starting) gets shown for 10 seconds since the checks get done in intervals of 3 seconds ( — interval=3s) and we specified a — timeout=1s.

Let’s reduce the interval to 1 second so that we can see the health results faster.

Let’s also reduce the retries from the default of 3 to just 1 using: — retries=1

In a PROD environment you will almost never use retries = 1. The 3 is a much better realistic real-life value.

Add this to Dockerfile using

nano Dockerfile

Build the image using

Let’s start up a container to see the result.

Notice I am checking the container status every .4 seconds.

Expected output:

For 0.8 seconds the health status is (health: starting)

After one second the status changes to (unhealthy).

It is up to you as admin to tinker these settings to suit your actual prod env:

You as admin must also determine in your prod env what appropriate health check commands would be. Web server containers, database containers, haproxy containers all have different health check requirements.

One second is too low a duration: it was just used here to show quickly how the status changes.

Just to see what healthy looks like, let’s do a sample health check that succeeds.

Add this to Dockerfile using

nano Dockerfile

Build the image using

Let’s start up a container to see the result.

Expected output:

Notice how the status changes to (healthy) in less that a second: the sleep .1 sleeps successfully for a tenth of a second then returns a successful status return code.

Unfortunately the docker ps -a command status filter does NOT match containers by HEALTH status. You can ONLY filter using created, restarting, running, removing, paused, exited and dead.

You cannot execute: docker ps — filter status=healthy

You cannot execute: docker ps — filter status=unhealthy

You have to use:

docker ps -a | grep ‘(healthy)’

and

docker ps -a | grep ‘(unhealthy)’

Dockerfile EXPOSE Ports

In this section you will learn how Dockerfile uses EXPOSE to expose ports of the container.

Containers are isolated running processes. They must specify explicitly which ports are accessible to other containers.

A port is the official way a process allows other processes to contact it and send it commands.

For example with Apache port 80 in normally exposed. Apache hides isolated within its container. The ONLY way to get it to do something is to access it via port 80.

The EXPOSE instruction declares the ports the container listens on.

You can state whether the port listens on the TCP or UDP protocol, The default is TCP if the protocol is not specified.

The EXPOSE instruction does not actually publish the port — it does not make it available to others.

EXPOSE only serves as documentation. It declares which ports in the container are intended to be available to be published.

From https://docs.docker.com/engine/reference/builder/#expose

To actually publish the port when running the container, use the -p flag on docker run to publish and map one or more ports, or the -P flag to publish all exposed ports and map them to high-order ports.

By default, EXPOSE assumes TCP. You can also specify UDP:

EXPOSE 80/tcp

EXPOSE 80/udp

In this tutorial we are going to expose port 80, tcp and udp.

Edit your Dockerfile to look like:

nano Dockerfile

Build the image using

Let’s start up a container to see the result.

Expected output

In the ports column we can see those ports exposed: but they are not available for use. We must publish them. We do this using -p 30000:80/tcp on the docker run command.

-p 30000:80/tcp

The 30000 specifies the host port number. 80/tcp specifies the container port number.

Let’s create the container and see the result:

Expected output:

0.0.0.0:30000->80/tcp

Port 30000 on localhost is mapped to port 80 in the container.

We can check that port 30000 is now open on the host:

The ss command is used to show information about sockets. It is similar to netstat command. ( The netstat command no longer exists in default installation of the CentOS distro. It is replaced with service command. )

short, long versions of the options:

  1. -t, — tcp display only TCP sockets
  2. -a, — all display all sockets
  3. -n, — numeric don’t resolve service names, show numeric port number

Expected output

We can see that port 30000 is now listening on the host.

The 30000 has no special meaning. Its just used here as an easy to find port number.

Let’s publish udp port 80 as well. Run:

Check to see if the publish worked:

Expected output

Noticed this time I used -u argument to show udp ports.

Dockerfile ENV Variables

You can use environment variables to send values to running containers.

They are part of the environment in which a container runs: you will see how this works below.

Syntax:

ENV

ENV =

The ENV instruction sets the environment variable to the value .

Examples:

Let’s use our small Alpine Linux distro to see env variables within the env.

Create a Dockerfile with this content:

Notice I used 2 different ways to declare env variables: one is space separated, one is = separated.

Build the image using

Run:

Enter the printenv command at the # prompt:

Expected output

All the env variables we declared are there.

You can override the env variables when using docker run:

Run:

If you now enter the container you will see my42 is 44000.

Expected output

You now have some practical experience declaring ENV variables in a Dockerfile as well as overriding them when using docker run -e ‘my-env-var-name=new value’

You can also inspect the content of env variables using printenv. ( You could also use set or env to show env variables at the shell prompt. )

More information https://en.wikipedia.org/wiki/Environment_variable

https://docs.docker.com/engine/reference/builder/#env

https://docs.docker.com/engine/reference/builder/#environment-replacement

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

Reference:https://www.alibabacloud.com/blog/getting-to-know-dockerfile-instructions-part-2_594331?spm=a2c41.12473723.0.0

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