In the previous lecture, we saw how to install Docker and dockerize an app. In this lecture, we will see how to create and work with Docker images.
Pre-requisites:
Make sure that docker is installed and functional:
docker info
which should list information similar to the one below:
Containers: 41
Running: 0
Paused: 0
Stopped: 41
Images: 47
Server Version: 17.03.1-ce
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 132
Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
. . .
. . .
Username: kalharbi
Registry: https://index.docker.io/v1/
Experimental: true
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Finding Docker images
- We can list all available images using the command
docker search
.
docker search httpd
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
httpd The Apache HTTP Server Project 2195 [OK]
hypriot/rpi-busybox-httpd Raspberry Pi compatible Docker Image with a … 45
centos/httpd 21 [OK]
- We can also visit the website of the Docker Hub registry tand search for images.
Pulling images
- We can download images hosted on the Docker Hub using the command
docker pull image_name:tag_name
. By default, if we do not specify the tag name, Docker will download the latest tag.
$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a5a6f2f73cd8: Already exists
1ba02017c4b2: Pull complete
33b176c904de: Pull complete
Digest: sha256:5d32f60db294b5deb55d078cd4feb410ad88e6fe77500c87d3970eca97f54dba
Status: Downloaded newer image for nginx:latest
- When we run a container from an image with the docker run command, if the image is not available locally on the host then Docker will download it from docker hub (using docker pull).
Listing Docker images
We can list all built images using the command docker images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 568c4670fa80 2 days ago 109MB
my-web-app latest 913cbc0dd0fa 2 days ago 91.8MB
httpd 2-alpine 11fc0c2a2dfa 2 weeks ago 91.8MB
openjdk 8-jdk-alpine 97bc1352afde 5 weeks ago 103MB
alpine latest 196d12cf6ab1 2 months ago 4.41MB
Showing the history of an image
- We can inspect all the changes that occurred to a docker image using the command
docker history <image_name_or_id
. The output will include all the changes that made to the layers that represent the filesystem when the image was built.
$ docker history nginx
IMAGE CREATED CREATED BY SIZE COMMENT
568c4670fa80 2 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 2 days ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0B
<missing> 2 days ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B
<missing> 2 days ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B
<missing> 2 days ago /bin/sh -c set -x && apt-get update && apt… 53.8MB
<missing> 2 days ago /bin/sh -c #(nop) ENV NJS_VERSION=1.15.7.0.… 0B
<missing> 2 days ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.15.7-… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:dab9baf938799c515… 55.3MB
Building your own images
The recommended way of building images is using the docker build
command with a Dockerfile.
The Dockerfile is a definition file that uses a specific set of instructions for building and customizing Docker images.
We will build a docker container that runs Apache httpd web server and changes the content of the default index.html file.
To build an image using a Dockerfile, create a file named Dockerfile and open it in your text editor:
mkdir web-app-in-docker cd web-app-in-docker touch index.html nano index.html
Add the following content to the index.html file.
<!DOCTYPE html> <html> <head> <title>Hello Docker Apache httpd</title> </head> <body> <h1>My First Docker container running Apache httpd</h1> </body> </html>
Crate a Dockerfile
touch Dockerfile nano Dockerfile
Add the following content to the Dockerfile:
FROM alpine:3.8 LABEL maintainer="khalid@example.com" RUN apk update && apk add apache2 && mkdir -p /run/apache2 RUN echo "ServerName localhost" >> /etc/apache2/httpd.conf COPY index.html /var/www/localhost/htdocs/index.html CMD ["httpd", "-D", "FOREGROUND"] EXPOSE 80
Build the image
docker build -t my-apache-image .
Sending build context to Docker daemon 3.072kB Step 1/7 : FROM alpine:3.8 ---> 196d12cf6ab1 Step 2/7 : LABEL maintainer="khalid@example.com" ---> Using cache ---> bff42fd19cf6 Step 3/7 : RUN apk update && apk add apache2 && mkdir -p /run/apache2 ---> Using cache ---> 7c41ae5316f8 Step 4/7 : RUN echo "ServerName localhost" >> /etc/apache2/httpd.conf ---> Running in b6b794eb52fe Removing intermediate container b6b794eb52fe ---> 3a66ec0e626e Step 5/7 : COPY index.html /var/www/localhost/htdocs/index.html ---> c121986176a7 Step 6/7 : CMD ["httpd", "-D", "FOREGROUND"] ---> Running in efeb3b7e577c Removing intermediate container efeb3b7e577c ---> 012eb86f76f9 Step 7/7 : EXPOSE 80 ---> Running in 6fede68d56e3 Removing intermediate container 6fede68d56e3 ---> a50d38a2f0cd Successfully built a50d38a2f0cd Successfully tagged my-apache-image:latest
Running a container from an image
To run the image we built above, use the
docker run
command:docker run -p 8080:80 my-apache-image
Let’s see what happened:
We have launched a new container from the image we built, my-apache-image.
The Dockerfile has a command to edit the default apache httpd config file and set localhost as the serverName.
The Dockerfile has a command to copy the
index.html
to Apache httpd’s root directory.We have specified the command
httpd -D FOREGROUND
for the container to run inside the Dockerfile as a value for theCMD
instruction.- This will launch apache httpd in the foreground to keep our container running. If we do not specify this option, then apache httpd will run in the background inside the container but Docker will stop the container immediately because there’s no process running in the foreground.
We have also specified the network ports that we want Docker to publish on the container and map to the host port number using the flag
-p HOST_PORT:CONTAINER_PORT
.- The flag
-p 8080:80
will bind port 80 on the container to port 8080 on the host.
- The flag
We can also bind to a specific network interface. Stop the currently running container using
CTRL-C
and run:docker run -p 127.0.0.1:8080:80 my-apache-image
To list running containers and find information about them, run
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3e254ac7a1ac my-apache-image "httpd -D FOREGROUND" 4 seconds ago Up 2 seconds 127.0.0.1:8080->80/tcp amazing_pascal
We can see that under the PORTS column Docker is binding port
80
on the container to127.0.0.1:8080
on the host. Open your browser and go to `http://127.0.0.1:8080. You should see the custom html web page we created:
Dockerfile instructions
Please refer to the Dockerfile reference to see all available Dockerfile instructions.
Sharing an image
Docker images can be distributed and shared on a registry such as the Docker Hub.
Create an account on the Docker Hub and verify your email address for the email you receive after signing up.
Sign into the Docker Hub using the docker command:
docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: kalharbi Password: Login Succeeded
We will create a custom image using a Dockerfile. Our image will use alpine:3.8 as the base image and install apache httpd on it.
FROM alpine:3.8 LABEL maintainer="your-email-address@example.com" RUN apk update && apk add apache2 && mkdir -p /run/apache2 RUN echo "ServerName localhost" >> /etc/apache2/httpd.conf CMD ["httpd", "-D", "FOREGROUND"] EXPOSE 80
Build the image. In order to have a publishable image on Docker Hub, we need to tag the image with our user-name/image-name. Otherwise, we will not be able to push it to Docker Hub because it will be considered a root repository, which is managed by the Docker Inc. team. Build the image and tag it with your user name:
docker build -t kalharbi/alpine-httpd .
Use the
docker images
command to list the available images on your machine:docker images
REPOSITORY TAG IMAGE ID CREATED SIZE kalharbi/alpine-httpd latest 3202914b65c5 10 minutes ago 8.97MB
Push the image to Docker Hub. We can distribute the image and share it on Docker Hub using the
docker push
command.docker push kalharbi/alpine-httpd
The push refers to repository [docker.io/kalharbi/alpine-httpd] c184b7dad79d: Pushed 781b9ebdce45: Pushed df64d3292fd6: Mounted from library/alpine latest: digest: sha256:0d8753071f49f745cf208a8597701c40f1db6d5190c59d925203ba9e18d6e565 size: 947
We can now see our uploaded image on Docker Hub.
Anyone can pull the image using the command
docker pull kalharbi/alpine-httpd
Deleting an image
You can delete an image using the command
docker rmi <image_name_or_id>
:docker rmi my-apache-image
If the image is being used by a container, then you need to delete the container first using the command
docker rm <container_name_or_id>
or to force deleting the image that is being used by a container using the-f
flag:docker rmi -f my-apache-image