Docker knowledge to get you through the day
Mar 15, 2021 · 6 min readFollowing on from the “Git commands to get you through the day” post, Paddy Morgan and I delivered a Docker 101 workshop today at work.
This post covers what we ran through.
Time allocation: 60 minutes
This workshop will be a high level overview of the basic docker commands you will use daily. It’s an entry level workshop, so if you’re comfortable with docker on the CLI, this probably isn’t for you.
What we will cover:
- Pulling
- Running basic commands
- Defining
- Building
- Running more advanced commands
- Process management
- Cleanup
- Tidbits
Some up front terminology
- Image - A definition of an environment.
- Container - A virtualised run time environment of a docker image.
Commands
We need to make sure we have docker
installed, so let’s run that first.
docker
If Docker is installed, this will output a raft of commands that we can make use of. If you haven’t got Docker, checkout the installation page.
You may notice that some of the commands are the same, e.g.
docker images
docker image ls
Take some time to review the output from the main docker
command.
Pulling
Let’s start with understanding what images we have on our machine.
docker images
This shows us all the images that are pre-built and stored on your machine. Any images listed here are available to be run locally. If you have not used Docker before, the list is likely to be empty.
Let’s pull down the hello-world
image.
docker pull hello-world
If you now run docker images
you should see something very similar to this:
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 7 days ago 13.3kB
Running basic commands
Let’s now run that image as a container.
docker run hello-world
So docker
is the main command. run
is the subcommand which allows us to run the hello-world
image as a container.
If we now run docker ps -a
you will see containers that are: running, have ran and stopped.
❯ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fd4a9f1b80b hello-world "/hello" About a minute ago Exited (0) About a minute ago practical_blackwell
Ideally, we want to clean-up after ourselves. So lets run the container again.
docker run --rm hello-world
Notice the --rm
flag, which will remove the container once execution has finished.
If we run docker ps -a
again you will notice there isn’t a new entry in the list.
Defining
Let’s cover two scenarios
- An environment you want to work in.
- Shipping something.
Environment
Let’s look at a VS Code Dev Environment.
Key items to cover off are:
FROM
- The base image isgolang:1
.- This in turn will have a base image, so essentially these can be chained.
- Some base images will be low level linux distructions like Ubuntu, or Alpine.
- Some base images will provide extra capabilities on top of the OS, like
golang
.
ENV
- Environment variables for the image.ARG
- Arguments that can be overridden when building the image.COPY
- The ability to copy files from the host into the image (These will persist in the image).- The host file is on the left, whilst the image location is on the right hand side of the declaration.
RUN
- Running commands to build the image.- You can see that commands are grouped together as one
RUN
command. - This is to keep those defined as a “layer”.
- You can see that commands are grouped together as one
Shipping something
Let’s look at Hagen which is a CLI tool for getting some data out of GitHub. This is running a Go binary inside the container.
Key items to cover off are:
alpine
- Base images are generally linux based.- Alpine is a very small linux distribution.
- If you can use it, it will keep your images small (which ultimately saves time and money).
- Alpine, by default, uses
apk
notapt
to install packages, this may catch people out to start with.
FROM scratch
- Start with a bare bones container, nothing in there.- This is classed as a multi-stage build.
ENTRYPOINT
- This defines what should be executed when the image is instantiated as a container.- Here you can see we are running the
hagen
command, which has been placed in/usr/bin/
.
- Here you can see we are running the
CMD
- Here we usingCMD
to pass--help
tohagen
.- So if you do not pass any other arguments into the container when running it, it will provide you will a help menu.
Building
Let’s look at the Hagen example again.
docker build -t benmatselby/hagen .
Breaking this down we have docker build
as the command.
-t
defines the string we will tag the image with. You can specify multiple tags, and they will all show when you run docker images
.
And finally the .
provides the context to the build command.
Running more advanced commands
For a more in-depth review of what you can do whilst running containers, please see the documentation.
An example of sharing environment variables, and files from the host to the container.
docker run \
--rm \
-t \
-eGITHUB_OWNER \
-eGITHUB_ORG \
-eGITHUB_TOKEN \
-v "${HOME}/.benmatselby":/root/.benmatselby \
benmatselby/hagen
Breaking this down.
--rm
will remove the container from the system once finished execution.-t
allocates atty
. See this.-e
provides environment variables to the container.- If the names match you can do it this way.
- If not you can provide them in the
-e foo=bar
format.
-v
defines a volume, which is essentially a file share between the host and the container.- The format is
host:container
. - This allows us to share the configuration used for hagen, with the container.
- The format is
What if you want to get your terminal back, and run the container unsupervised? Then you can do this
$ docker run \
--rm \
-p 8080:80 \
-v "$(pwd):/usr/share/nginx/html" \
-d \
nginx
dcc55061e1118f7b6ccf2c3708d717531bf0c92327ed42f94f08d13020e901ea
$ curl http://localhost:8080/
The extra bits here are:
-p 8080:80
links the host port (8080
) to the container port (80
) that has been exposed.-d
will disconnect the container from your terminal, and then output the container id back to you.- You can see after the
docker run
command, a unique ID presented back to you. This is the running container process ID. - The example above then hits
nginx
and tries to retrieve some HTML. If yourpwd
(current working directory) does not have any HTML, this will give a 404.
Process management
Want to know what processes are running?
docker ps
will give the current containers running.
docker ps -a
will give you all the containers that are running and stopped.
Want to connect to a container that is running, then you can do this:
docker exec -it dcc55061e1118f7b6ccf2c3708d717531bf0c92327ed42f94f08d13020e901ea bash
Breaking this down, we have docker exec
for executing something, but we run interactively with -it
options and then run bash
. This could be zsh
or actually any command that is available in the container. Notice we are using the same container from the nginx
example.
Want to know more about a running container, then run
docker inspect dcc55061e1118f7b6ccf2c3708d717531bf0c92327ed42f94f08d13020e901ea
To stop a container you can run
docker stop dcc55061e1118f7b6ccf2c3708d717531bf0c92327ed42f94f08d13020e901ea
Clean-up
These commands will help keep your machine tidy:
docker rm $(docker ps -aq)
- Remove all containers.docker rmi $(docker images -q)
- Remove all images stored locally.docker rmi $(docker images -f "dangling=true" -q)
- Remove all images that are not being used - “dangling”.docker stop $(docker ps -aq)
- Stop all containers running.
Or
docker system prune