How to Work with Docker Images
This post feels like a step back from my previous post on managing services on Docker Swarm. The major reason for this: when working with a multi-node Docker Swarm cluster, Docker images must be on each cluster. I used two ways to get images onto the cluster: traditional file transfer and via Docker Hub.
I had to learn how to work with Docker images by:
- Build images
- Tag images
- Save built images to disk
- Load images from disk
- Push images
- Pull images
Requirements
If you would like to follow along this article, these are the requirements:
- Docker Installed
- A working Dockerfile, I am using this one from a previous article.
To build a Docker image, have a working Dockerfile
. I will be using
the
rails-git-version
app built previously that has this basic Dockerfile:
FROM ruby:2.5.0-slim
RUN apt-get update && apt-get install -qq -y --no-install-recommends \
build-essential \
libsqlite3-dev \
nodejs \
sqlite3 \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"]
Docker Build
The Docker build command is simply: docker build .
, which builds an
image using Dockerfile.
vagrant@manager:/vagrant$ sudo docker build .
Sending build context to Docker daemon 446.5kB
Step 1/8 : FROM ruby:2.5.0-slim
---> f7d41825e9a8
Step 2/8 : RUN apt-get update && apt-get install -qq -y --no-install-recommends build-essential libsqlite3-dev nodejs sqlite3 && rm -rf /var/lib/apt/lists/*
...
Removing intermediate container f2fe6b9bc274
---> 182196cb787b
Successfully built 182196cb787b
vagrant@manager:/vagrant$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 182196cb787b About an hour ago 524MB
The image built, but the name is <none>
and tagged as <none>
. The
only way to use this is image is to use its image ID: 182196cb787b,
not useful when working with Docker Swarm, which requires images have
names.
Tagging Images
To tag an image, use the associated image ID in the command format:
docker tag <image ID> <name>:<tag>
vagrant@manager:/vagrant$ sudo docker tag 182196cb787b test
vagrant@manager:/vagrant$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 182196cb787b About an hour ago 524MB
The default tag is latest
, here is how to specify another:
vagrant@manager:/vagrant$ sudo docker tag 182196cb787b test:v.2.10.0
vagrant@manager:/vagrant$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 182196cb787b About an hour ago 524MB
test v.2.10.0 182196cb787b About an hour ago 524MB
Save Image to Disk
After creating a Docker image, to save the image to disk, so you can put it on an external drive, email it, FTP it, SCP it, etc. use the Docker save command, which has the format:
docker save -o <image filename> <image>
vagrant@manager:/vagrant$ sudo docker save -o test.docker_image test
vagrant@manager:/vagrant$ ll
total 529760
drwxr-xr-x 1 vagrant vagrant 238 Sep 6 2018 ./
drwxr-xr-x 24 root root 4096 Sep 5 22:49 ../
drwxr-xr-x 1 vagrant vagrant 442 Sep 5 22:17 .git/
-rw-r--r-- 1 vagrant vagrant 536 Sep 5 22:17 .gitignore
-rw------- 1 vagrant vagrant 542459392 Sep 6 2018 test.docker_image
drwxr-xr-x 1 vagrant vagrant 102 Aug 24 22:25 .vagrant/
-rw-r--r-- 1 vagrant vagrant 1427 Sep 1 01:17 Vagrantfile
This is the easiest way to make Docker images accessible.
Load Image from Disk
Now that you have a Docker image on disk, how to load a Docker image
from disk so Docker services, such as docker run
, or docker service
create
can use it? Use the docker load
command, which has the
command format of:
docker load < <image filename>
Let’s delete the current image from Docker and load it back:
vagrant@manager:/vagrant$ sudo docker rmi test
Untagged: test:latest
Deleted: sha256:182196cb787b222672fad14609077fb24e05803cfdc9317ea4303eb6a4e1248b
Deleted: sha256:1ddecb272c0103264ad84b115541f3946a1ea7ceff0c6524f35b176748c3249a
Deleted: sha256:28e2a7e3ce6a31fe0eb7ff2dd6cfdfa458115963b827454a2b3a2b0175f7cfee
vagrant@manager:/vagrant$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
vagrant@manager:/vagrant$ sudo docker load < test.docker_image
be46842105ce: Loading layer [==================================================>] 112.4MB/112.4MB
15e0fab9d6f7: Loading layer [==================================================>] 447kB/447kB
Loaded image: test:latest
vagrant@manager:/vagrant$ sudo docker images test
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 182196cb787b About an hour ago 524MB
Push to Docker Hub
Another way to load the Docker image: put it on Docker Hub! It’s a Docker image registry. Once an image is on there, any system that can connect to Docker Hub can load the image.
Login
After creating an account on Docker Hub, login on the command line
using docker login
command:
vagrant@manager:/vagrant$ sudo 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: andrewrgr
Password:
WARNING! Your password will be stored unencrypted in /home/vagrant/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
Rename Image
To push the image to Docker Hub, rename the image to the format:
<docker hub username>/<image name>
The reason for this: the default registry for the docker push
command is: https://docker.io
(which is equivalent to Docker
Hub). Adding that in front of the image, the full URI would become:
https://docker.io/docker_hub_username/image_name
For example:
vagrant@manager:/vagrant$ sudo docker images test
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest 182196cb787b 9 hours ago 524MB
vagrant@manager:/vagrant$ sudo docker tag 182196cb787b andrewrgr/test
This will make the full URI to be: https://docker.io/andrewrgr/test, which makes this image accessible.
Docker Push
Now that the image is ready, let’s push it up to Docker Hub!
vagrant@manager:/vagrant$ sudo docker push andrewrgr/test
The push refers to repository [docker.io/andrewrgr/test]
15e0fab9d6f7: Pushing [> ] 2.56kB/164.7kB
be46842105ce: Pushing [=> ] 2.777MB/107.8MB
074f81d79383: Pushing [==================================================>] 9.728kB
46823c0a1fdd: Pushing 1.536kB
d25206577e0d: Pushing [> ] 528.3kB/238.7MB
ec5946222cf1: Waiting
064a7e7c616b: Waiting
7825b4ce4afe: Waiting
c4376fdf62a5: Waiting
e1df5dc88d2c: Waiting
...
Docker Pull
Now the image can be pull down like any other Docker image:
vagrant@manager:/vagrant$ sudo docker pull andrewrgr/test
Using default tag: latest
latest: Pulling from andrewrgr/test
Digest: sha256:e583f595f6d99983c33ff2070a6b0767618872a49b2906cd6d43f90e56a4f04e
Status: Image is up to date for andrewrgr/test:latest
Conclusion
This time we went over how to work with Docker images through tags, at a file level: saving images to disk, loading images from disk, and using Docker Hub as a way to store and access images remotely.