{% extends 'dockerfile/_dockerfile.html' %} {% load staticfiles %}{% load google_analytics %}{% load navactive %} {% block page_js %} {{ block.super }} {% endblock page_js %} {% block content %}

Dockerfile tutorial

Level 2 – ENTRYPOINT, USER & EXPOSE

In this section we will cover three important instructions: ENTRYPOINT, USER and EXPOSE. These commands will help you write more advanced and therefore more complex containers. At the end of this tutorial you will be able to understand and write this Dockerfile:

# Memcached
#
# VERSION       42

# use the ubuntu base image provided by dotCloud
FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# install memcached
RUN apt-get install -y memcached

# Launch memcached when launching the container
ENTRYPOINT ["memcached"]

# run memcached as the daemon user
USER daemon

# expose memcached port
EXPOSE 11211

Ready? Go!

Requirements

Before taking this tutorial, please make sure that you completed and understand all instructions covered by the Level 1 Dockerfile tutorial (FROM, RUN, MAINTAINER, #). If this is not the case please start with Level 1.

The ENTRYPOINT instruction

The ENTRYPOINT instruction permits you to trigger a command as soon as the container starts.

Whale You Be My Container?

Let’s say you want your container to execute echo “Whale You Be My Container?” as soon as it starts. Then you will use:

ENTRYPOINT echo “Whale You Be My Container?”

Let’s try it!

root@precise64:/home/vagrant/dockerfiles/tutorial1# cat Dockerfile_whale_you_be_my_container
# Whale you be my container?
#
# VERSION       0.42

# use the ubuntu base image provided by dotCloud
FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

# say hello when the container is launched
ENTRYPOINT echo "Whale you be my container"
root@precise64:/home/vagrant/dockerfiles/tutorial1# docker build -t whaleyoubemycontainer - < Dockerfile_whale_you_be_my_container
Uploading context 2048 bytes
Step 1 : FROM ubuntu
Pulling repository ubuntu
 ---> b750fe79269dlayersantl) from ubuntu, endpoint: https://cdn-registry-1.docker.io/v1/
Step 2 : MAINTAINER Victor Coisne victor.coisne@dotcloud.com
 ---> Running in 2fd00b89982b
 ---> a2163a4bb4e6
Step 3 : ENTRYPOINT echo "Whale you be my container"
 ---> Running in 81f46dafd81a
 ---> f62c1b30adad
Successfully built f62c1b30adad
root@precise64:/home/vagrant/dockerfiles/tutorial1# docker run whaleyoubemycontainer
Whale you be my container
root@precise64:/home/vagrant/dockerfiles/tutorial1#

There are two syntaxes for the ENTRYPOINT instruction. Instead of command param1 param2 … you could also use the exec format:

ENTRYPOINT ["echo", "Whale you be my container"]

This is actually the preferred form, so we will use this form from now on.

wc

The ENTRYPOINT instruction helps to configure a container that you can run as an executable. That is, when you specify an ENTRYPOINT, the whole container runs as if it was just that executable. Let’s see an example with a a container running wc –l as ENTRYPOINT

root@precise64:/home/vagrant/dockerfiles/tutorial1# cat Dockerfile_wc
# This is wc
#
# VERSION       0.42

# use the ubuntu base image provided by dotCloud
FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

# count lines with wc
ENTRYPOINT ["wc", "-l"]
root@precise64:/home/vagrant/dockerfiles/tutorial1# docker build -t wc - < Dockerfile_wc
Uploading context 2048 bytes
Step 1 : FROM ubuntu
 ---> b750fe79269d
Step 2 : MAINTAINER Victor Coisne victor.coisne@dotcloud.com
 ---> Using cache
 ---> a2163a4bb4e6
Step 3 : ENTRYPOINT ["wc", "-l"]
 ---> Using cache
 ---> 52504f229d30
Successfully built 52504f229d30
root@precise64:/home/vagrant/dockerfiles/tutorial1# cat /etc/passwd | docker run -i wc
28

memcached

Remember our Dockerfile from Level 1? We can now add an ENTRYPOINT. Memcached needs to be run by the user daemon. So the ENTRYPOINT instruction will look like this:

ENTRYPOINT ["memcached", "-u", "daemon"]

This is the resulting Dockerfile

# Memcached
#
# VERSION       2.0

# use the ubuntu base image provided by dotCloud
FROM ubuntu
MAINTAINER Guillaume J. Charmes guillaume@dotcloud.com
# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# install memcached
RUN apt-get install -y memcached

# Launch memcached when launching the container
ENTRYPOINT ["memcached", "-u", "daemon"]

The USER instruction

As we have seen earlier with Memcached, you may need to run the ENTRYPOINT commands as a different user than root. In the previous example, Memcached already has the option to run as another user. But it is not the case for all services/programs. Here comes the USER instruction. As you may have already understood, the USER instruction sets the username or UID to use when running the image. With this new instruction, instead of this

ENTRYPOINT ["memcached", "-u", "daemon"]

We can now use this

ENTRYPOINT ["memcached"]
USER daemon

Memcached

Here is our updated Memcached Dockerfile

# Memcached
#
# VERSION       2.1

# use the ubuntu base image provided by dotCloud
FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# install memcached
RUN apt-get install -y memcached

# Launch memcached when launching the container
ENTRYPOINT ["memcached"]

# run memcached as the daemon user
USER daemon

The EXPOSE instruction

The EXPOSE instruction sets ports to be exposed when running the image.

Memcached

Memcached uses port 11211, so we have to expose this port in order to be able to talk to the Memcached container from outside the container. This is simply done with this line

EXPOSE 11211

By doing so, the container will sets the port 11211 to be exposed when running the Memcached image.
The final Dockerfile now looks like this:

# Memcached
#
# VERSION       2.2

# use the ubuntu base image provided by dotCloud
FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# install memcached
RUN apt-get install -y memcached

# Launch memcached when launching the container
ENTRYPOINT ["memcached"]

# run memcached as the daemon user
USER daemon

# expose memcached port
EXPOSE 11211

Playing with our Memcached image

So, we are on a server and we need Memcached. Let's use what we have just learned :)

Building the image

First, let’s build the image, from the Dockerfile.

root@precise64:/home/vagrant/dockerfiles/tutorial1# cat Dockerfile
# Memcached
#
# VERSION       2.2

# use the ubuntu base image provided by dotCloud
FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# install memcached
RUN apt-get install -y memcached

# Launch memcached when launching the container
ENTRYPOINT ["memcached"]

# run memcached as the daemon user
USER daemon

# expose memcached port
EXPOSE 11211
root@precise64:/home/vagrant/dockerfiles/tutorial1# docker build -t memcached - < Dockerfile
Uploading context 2560 bytes
Step 1 : FROM ubuntu
 ---> 8dbd9e392a96
Step 2 : MAINTAINER Victor Coisne victor.coisne@dotcloud.com
 ---> Using cache
 ---> dee832c11d42
Step 3 : RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
 ---> Using cache
 ---> 66678b24bab4
Step 4 : RUN apt-get update
 ---> Using cache
 ---> 2fbfe4f542d8
Step 5 : RUN apt-get install -y memcached
 ---> Using cache
 ---> 80c7e70e69a1
Step 6 : ENTRYPOINT ["memcached"]
 ---> Running in df59a42eeaa7
 ---> 090512aab2ac
Step 7 : USER daemon
 ---> Running in f4618f8c72ec
 ---> 264b9e444135
Step 8 : EXPOSE 11211
 ---> Running in e339e4cb6838
 ---> 42a44756989e
Successfully built 42a44756989e

Now let’s launch it. We use the -p flag to publish the port publicly.

root@precise64:/home/vagrant/dockerfiles/tutorial1# docker run -p 11211 memcached

Memcached is running :) Now which port should we use to access it from outside the container? As we asked for it with the EXPOSE instruction, the container is exposing the 11211 port, and we used -p publish it to our system. We can use the docker ps command in order to get the port we should use from outside the container to access Memcached inside the container.

root@precise64:/home/vagrant/dockerfiles/tutorial1# docker ps
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS                           NAMES
1aa7a504438c        memcached:latest    memcached           2 minutes ago       Up 2 minutes        0.0.0.0:49153->11211/tcp        blue_whale

In this example the column PORTS shows that we should use the port 49153.
NOTE: you could also use the docker port or the docker inspect commands to retrieve the right port number.

Python

We will here use python to play with Memcached, but you can use any language (Go, PHP, Ruby, …). This is a simple Python script to use your Memcached (Don’t forget to update the port number, you will probably not have the same).

# run this command if import memcache fails
# pip install python-memcached

import memcache

ip = 'localhost'
port = 49153

mc = memcache.Client(["{0}:{1}".format(ip, port)], debug=0)
mc.set("MDM", "Guillaume J. C.")
value = mc.get("MDM")

print value

Let’s run it!

root@precise64:/home/vagrant/dockerfiles/tutorial2# python test.py
Guillaume J. C.

Congratulations! You just used your first containerized Memcached server :)

Test your Dockerfile skills - Level 2

Questions

What is the Dockerfile instruction to specify the base image?

Which Dockerfile instruction sets the default command for your image?

What is the character used to add comments in Dockerfiles?

Which Dockerfile instruction sets the username to use when running the image?

What is the Dockerfile instruction to execute any command on the current image and commit the results?

Which Dockerfile instruction sets ports to be exposed when running the image?

What is the Dockerfile instruction to specify the maintainer of the Dockerfile?

Which Dockerfile instruction lets you trigger a command as soon as the container starts?


DockerFill

Your best friend Roberto Hashioka sent you a Dockerfile, but some parts were lost in the ocean. Can you find the missing parts?

# Redis
#
# VERSION       0.42

# use the ubuntu base image provided by dotCloud
  ub

MAINT Ro Ha roberto.hashioka@dotcloud.com

# make sure the package repository is up to date
 echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
 apt-get update

# install wget (required for redis installation)
 apt-get install -y wget

# install make (required for redis installation)
 apt-get install -y make

# install gcc (required for redis installation)
RUN apt-get install -y 

# install apache2
 wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable && make && make install

# launch redis when starting the image
 ["redis-server"]

# run as user dameon
 daemon

# expose port 6379
 6379


What's next?

We will be posting Level 3 in the next few weeks. Follow us on twitter and/or enter your email address to be alerted!

Email:

In the meantime, check out this blog post by Michael Crosby that describes Dockerfile Best Practices.

{% endblock %}