Learning about Docker, Docker Hub, and Containers
In this section, use whatever text editor you wish when updating the Dockerfile
mkdir imapex101_dockerfile
cd imapex101_dockerfile
touch Dockerfile
Dockerfiles use FROM
to indicate the base image
FROM debian:latest
the :latest
part indicates the "tag" to use on the image. Tags will be covered more later, but for now know that "latest" is a well understood standard tag in Docker. If you do NOT explicitly set a tag, Docker will look for a "latest" tag.
Dockerfile
docker build
docker run
GOTO 10
:-)
Dockerfile
, you need to rebuild your container.docker build
is the command to build the container image. When running use -t <repositoryname>:<tag>
format to provide a repository name and tag for the image. If you fail to specify, you can only refer to the image by the Image Id.<username or org>/<repo-name>
. This will be required if you plan to push
your image to a registry. .
looks in the current directory for Dockerfile
$ docker build -t <your username>/imapex101_dockerfile:latest .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
latest: Pulling from library/debian
357ea8c3d80b: Pull complete
Digest: sha256:ffb60fdbc401b2a692eef8d04616fca15905dce259d1499d96521970ed0bec36
Status: Downloaded newer image for debian:latest
---> 1b01529cc499
Successfully built 1b01529cc499
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<your username>/imapex101_dockerfile latest 1b01529cc499 23 hours ago 125.1 MB
docker run -it <your username>/imapex101_dockerfile /bin/bash
# now you're in the container, type exit to stop the container
root@80333d17d6c2:/# exit
-it
attaches to STDIN and creates a tty terminal to use/bin/bash
specifies the command to run inside the containerRun the docker ps -a
command to see the remnants of your container... you could restart it from this state with docker start, but another docker run would create a new one
$ docker ps -a
MAINTAINER
provides details about the author. Providing your name and email are typical. Email address within < >
symbols.RUN
command and leverage &&
to string commands together, and \
to allow readabilty with wrappingFROM debian:latest
MAINTAINER Your Name <email@domain.com>
# You can provide comments in Dockerfiles
# Install any needed packages for your application
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
curl \
dpkg-sig \
mercurial \
&& rm -rf /var/lib/apt/lists/*
docker build -t <your username>/imapex101_dockerfile:latest .
Step 2
and Step 3
and the running in
comments. Each command in the file, is a Step, and each step is a new layer. Minimizing the number of layers created is always a goal in Dockerfile creationEXPOSE
to specify what port(s) your container will use to host services externally. For example, if you are building a Web App Container, you'll likely expose port 80. FROM debian:latest
MAINTAINER Your Name <email@domain.com>
# You can provide comments in Dockerfiles
# Install any needed packages for your application
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
curl \
dpkg-sig \
mercurial \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
docker build -t <your username>/imapex101_dockerfile:latest .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
---> 1b01529cc499
Step 2 : MAINTAINER Hank Preston <hank.preston@gmail.com>
---> Using cache
---> 9f7054e99744
Step 3 : RUN apt-get update && apt-get install -y aufs-tools automake build-essential curl dpkg-sig mercurial && rm -rf /var/lib/apt/lists/*
---> Using cache
---> 331e39ad1dc4
Step 4 : EXPOSE 80
---> Running in 67d60d70e80b
---> 788c0d174e3d
Removing intermediate container 67d60d70e80b
Successfully built 788c0d174e3d
echo '#!/bin/bash' > hello_world.sh
echo "while [ 0 -eq 0 ]; do" >> hello_world.sh
echo "echo 'Hello World'" >> hello_world.sh
echo "sleep 2" >> hello_world.sh
echo "done" >> hello_world.sh
COPY
to bring in your code to the container. RUN
commands to take whatever actions needed. CMD
to instruct the container what to do upon execution. FROM debian:latest
MAINTAINER Your Name <email@domain.com>
# You can provide comments in Dockerfiles
# Install any needed packages for your application
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
curl \
dpkg-sig \
mercurial \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
COPY hello_world.sh /root/
RUN chmod +x /root/hello_world.sh
CMD ["/root/hello_world.sh"]
docker build -t <your username>/imapex101_dockerfile:latest .
Step 1 : FROM debian:latest
---> 1b01529cc499
Step 2 : MAINTAINER Hank Preston <hank.preston@gmail.com>
---> Using cache
---> 9f7054e99744
Step 3 : RUN apt-get update && apt-get install -y aufs-tools automake build-essential curl dpkg-sig mercurial && rm -rf /var/lib/apt/lists/*
---> Using cache
---> 331e39ad1dc4
Step 4 : EXPOSE 80
---> Using cache
---> 788c0d174e3d
Step 5 : COPY hello_world.sh /root/
---> 93105ac34a3b
Removing intermediate container d973d85f74f2
Step 6 : RUN chmod +x /root/hello_world.sh
---> Running in 888ee3e0c9fd
---> 2524c6f6b0bb
Removing intermediate container 888ee3e0c9fd
Step 7 : CMD /root/hello_world.sh
---> Running in 38a8f37827db
---> afde9a78e299
Removing intermediate container 38a8f37827db
Successfully built afde9a78e299
-d
to run our container in the background and print out the container iddocker run -d --name dockerfile <your username>/imapex101_dockerfile:latest
8b5b52eaa9a7c838c77bed791315a42ac7270e714c5fcd3ffbdbc49ef94b4316
# Checkout the status of running containers here
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b5b52eaa9a7 <your username>/imapex101_dockerfile:latest "/root/hello_world.sh" About a minute ago Up About a minute 80/tcp dockerfile
docker logs dockerfile
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
$ docker stop dockerfile
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b5b52eaa9a7 <your username>/imapex101_dockerfile:latest "/root/hello_world.sh" 4 minutes ago Exited (137) 14 seconds ago dockerfile
$ docker start dockerfile
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b5b52eaa9a7 <your username>/imapex101_dockerfile:latest "/root/hello_world.sh" 5 minutes ago Up 2 seconds 80/tcp dockerfile
The experiments were just a walkthrough of the very basics. Review these links for a more thorough discussion on best practices, and for examples of good Dockerfiles.
We'll be creating docker containers for many of our demos. Though we don't need the level of exactness used in commercial distributions, we do want to make sure we build respectable containers, that follow standards and best practices. Also, doing what we can to keep them small and quick to build/rebuild will help in our development practices.
For this exercise, build a new Dockerfile that...
Let's see what it looks like to use a registry other than hub.docker.com. We'll be using the image quay.io/repository/hpreston/demo
docker pull quay.io/hpreston/demo:latest
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/hpreston/demo latest afde9a78e299 58 minutes ago 371.3 MB
docker run -d --name quaydemo quay.io/hpreston/demo:latest
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
23a23fcb3d26 quay.io/hpreston/demo:latest "/root/hello_world.sh" 3 seconds ago Up 2 seconds 80/tcp quaydemo
docker logs quaydemo
Hello World
Hello World
Hello World
Hello World
Using the basic public registry from docker, or other public registries are fine for learning and experimentation. But enterprises of any size, will be looking for options for trusted registries. Understanding the options available, and how to work with them is important.
There is a hierarchy of objects within Docker that are worth having a solid understanding of.
What we commonly think of as a Docker container would better be described as a specificly tagged image, contained within a repository, managed by a user or organization, hosted on a particular registry
To be accurate, container is actually an instance of a tagged image that is running, or is currently stopped.
Within a single Repository, tags are used to provide different versions of what is typically the same application or service. Some common uses of the tags would be:
The tag :latest is a well understood standard in Docker to indicate a "default" image. If you do not specify a particular tag when building or pulling, latest will be assumed. It is up to the owner of the repository to manage what image is provided by :latest, and in fact it is possible to have a repository lacking a :latest tag. That is considered bad practice and should be avoided. Also remember that :latest rarely actually indicates the most recently built container...
docker pull python
Using default tag: latest
latest: Pulling from library/python
5c90d4a2d1a8: Pull complete
ab30c63719b1: Pull complete
c6072700a242: Pull complete
abb742d515b4: Pull complete
7663bd2e167e: Pull complete
d0f49e193c5a: Pull complete
28969a7d8e03: Pull complete
Digest: sha256:27cae89ba088e51a5c169f019ca6760d24a4e01c8453052631803a4785eda781
Status: Downloaded newer image for python:latest
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python latest 9152ad50a7f9 9 days ago 694.3 MB
python:latest
. It's a very large image, 694.3 MBs. That's fine for playing around, but for an actual container deployment, that's laughably large. Let's pull down a couple of other python images that are better for actual usage. docker pull python:slim
docker pull python:alpine
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python alpine 0298711f3095 9 days ago 73.04 MB
python slim bdec2259b96a 9 days ago 221.3 MB
python latest 9152ad50a7f9 9 days ago 694.3 MB
docker build -t <your username>/imapex101_dockerfile:fun .
docker build -t <your username>/imapex101_dockerfile:in .
docker build -t <your username>/imapex101_dockerfile:the .
docker build -t <your username>/imapex101_dockerfile:sun .
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<your username>/imapex101_dockerfile fun b6578662ca26 34 minutes ago 371.3 MB
<your username>/imapex101_dockerfile in b6578662ca26 34 minutes ago 371.3 MB
<your username>/imapex101_dockerfile latest b6578662ca26 34 minutes ago 371.3 MB
<your username>/imapex101_dockerfile sun b6578662ca26 34 minutes ago 371.3 MB
<your username>/imapex101_dockerfile the b6578662ca26 34 minutes ago 371.3 MB
To really use Docker effectively, you must understand the concept of tagging. Not only to make sure you are consuming containers as you intend, but also so you can setup your own repositories appropriately and as consumers will expect.
As we build our applications and demos, we'll need a way to easily make the updates and changes available for distribution. Though we could manually build, and push from our laptops during development, these are manual steps that take time away from the actual coding. Further... no one actually building applications works that manually. We need to be operating like developers.
Automated builds are not just available for Docker Hub, Quay.io offers them as well. Create an automated build on Quay.io for your GitHub project.