Basic notes on Docker
Some notes I took a while back on learning the basics of Docker.
Managing images
Lets use minideb, a small Debian-based linux:
$ docker pull bitnami/minideb
Using default tag: latest
latest: Pulling from bitnami/minideb
ba49d470d895: Pull complete
Digest: sha256:cbbc1db2617a7e5224f8dc692c990b723e4fe3ef69864544e7c14aa613c0ccb7
Status: Downloaded newer image for bitnami/minideb:latest
docker.io/bitnami/minideb:latest
We can see this new image is available locally with docker images
:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
bitnami/minideb latest c5eecd6244a8 3 days ago 120MB
And we can remove it with docker image rm <id>
:
$ docker image rm c5eecd6244a8
Untagged: bitnami/minideb:latest
Untagged: bitnami/minideb@sha256:cbbc1db2617a7e5224f8dc692c990b723e4fe3ef69864544e7c14aa613c0ccb7
Deleted: sha256:c5eecd6244a829084e2f788e3f877a5ab8ac63f9c8dc55c3cfff4f1d172fc23c
Deleted: sha256:44b47439f86a658d61565e3a9e86c1c9608b2ee8adb4f6e85005634e6f537f43
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
Running images in containers
We could run this image in a new container with docker run c5eecd6244a8
, but it would almost immediately return to our console. With docker container ls -a
, we’d see that this container ran and terminated:
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff11c7f3afb8 c5eecd6244a8 "/bin/bash" 29 seconds ago Exited (0) 28 seconds ago clever_franklin
# Delete this terminated container
$ docker container rm ff11c7f3afb8
What we want is to run interactively, so we’ll use docker run -it <id>
:
# In the host:
$ docker run -it c5eecd6244a8
# In the container!
root@25bca2749327:/# uname -a
Linux 25bca2749327 5.15.0-1042-azure #49~20.04.1-Ubuntu SMP Wed Jul 12 12:44:56 UTC 2023 x86_64 GNU/Linux
root@25bca2749327:/# cat /etc/os-release | grep NAME
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_CODENAME=bookworm
root@25bca2749327:/# exit
At this point, we’re back in our host. There’s still a terminated container:
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
25bca2749327 c5eecd6244a8 "/bin/bash" 2 minutes ago Exited (0) 49 seconds ago elegant_saha
$ docker container rm 25bca2749327
To avoid this, use docker run --rm
(NB, it has to be before the container name!):
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker run -it --rm c5eecd6244a8
root@21735047c8bb:/# hostname
21735047c8bb
root@21735047c8bb:/# exit
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Creating a container
Let’s make use of the minideb image as the basis for a derived image. We use a Dockerfile to describe the image we’ll create:
# The base image for our new image
FROM bitnami/minideb
# For a simple Rust service, see:
# https://aeshirey.github.io/code/2023/02/25/simple-rust-service-in-docker.html
# COPY <host-filename> <docker-filanem>
COPY rust-server my-rust-server
CMD ["./my-rust-server"]
To build this, we can use docker build <path>
, where <path>
is the directory in which the Dockerfile lives (eg, .
). Additionally, we’ll use the -t <name>:<tag>
to give our image a name and tag. If the tag is omitted, latest is used.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
bitnami/minideb latest c5eecd6244a8 3 days ago 120MB
$ docker build . -t my-simple-container
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 141B 0.0s
=> [internal] load metadata for docker.io/bitnami/minideb:latest 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 84B 0.0s
=> [1/2] FROM docker.io/bitnami/minideb:latest 0.0s
=> CACHED [2/2] COPY simple-server/simple-server my-simple-server 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:61a24712801a996b6ceefb378cd9ebccdb9caae8c58ea7acf17eaff0285666bb 0.0s
=> => naming to docker.io/library/my-simple-container 0.0s
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-simple-container latest 61a24712801a About a minut
bitnami/minideb latest c5eecd6244a8 3 days ago 120MB
Because our server exposes port 8080, we want our container to also expose it. Maybe we want to use the same port or maybe we want to remap it. Either way, we’ll use -p <host-port>:<container-port>
:
$ docker run --rm --init -p 8123:8080 fd83da080eab
Then we can connect in another shell on our host to communicate with this container:
$ curl 127.0.0.1:8123 -l -w "\n"
home
Extras
Need to ‘log into’ a container for an image you built to inspect it?
# Specify 'bash' as the process to run
$ docker run -p 8123:8080 --rm -it 61a24712801a bash
# image id ------^ ^-- command to run
Can’t CTRL-C from your docker run
?
Oops, can’t exit this container:
$ docker run --rm fd83da080eab
^C
From another shell:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
260c882a217e fd83da080eab "/my-simple-server" About a minute ago Up About a minute gracious_hawking
# ^------ this is the container we'll want to kill because oopsie
$ docker kill 260c882a217e
260c882a217e
Avoid this by including the --init
flag next time you docker run
:
$ docker run --rm --init fd83da080eab
^C$
How about accessing the host network?
If you use docker run --network=host
, then the container will be able to access the host network. For example:
# In the host OS:
$ ./rust-server &
$ curl 127.0.0.1:8080 -w "\n"
home
$ docker run -it --rm --network=host c5eecd6244a8
# Now in the container
root@hostname:/# curl 127.0.0.1:8080 -w "\n"
home
#
Exporting/importing images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 61a24712801a 30 minutes ago 131MB
my-simple-container latest fd83da080eab 30 minutes ago 131MB
bitnami/minideb latest c5eecd6244a8 3 days ago 120MB
$ docker save fd83da080eab | gzip > my-simple-container.tar.gz
$ file my-simple-container.tar.gz
my-simple-container.tar.gz: gzip compressed data, from Unix, original size modulo 2^32 135666688 gzip compressed data, reserved method, ASCII, extra field, encrypted, from FAT filesystem (MS-DOS, OS/2, NT), original size modulo 2^32 135666688
$ ls -lh my-simple-container.tar.gz
-rw-r--r-- 1 root root 41M Feb 17 04:48 my-simple-container.tar.gz
# Later/elsewhere, this can be loaded:
$ docker load < my-simple-container.tar.gz
Loaded image: my-simple-container:latest