{% extends 'dockerfile/_dockerfile.html' %} {% load staticfiles %}{% load google_analytics %}{% load navactive %} {% block page_js %} {{ block.super }} {% endblock page_js %} {% block content %}
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!
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 permits you to trigger a command as soon as the container starts.
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.
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
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"]
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
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 sets ports to be exposed when running the image.
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
So, we are on a server and we need Memcached. Let's use what we have just learned :)
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.
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 :)
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
We will be posting Level 3 in the next few weeks. Follow us on twitter and/or enter your email address to be alerted!
Follow @docker
In the meantime, check out this blog post by Michael Crosby that describes Dockerfile Best Practices.