When I’m learning a new technology, I’ve got to get in there and experiment to get the best result. And one particular piece of technology that I’ve been getting stuck into recently is Docker, the app containerisation platform that’s definitely on the shortlist for anyone hoping to move into the DevOps arena or move beyond normal virtualisation into something more application focused.
However, like a lot of technology that is either directly spawned from the DevOps mindset or fairly closely related, there’s something of an underlying assumption that you’re more Dev than Ops when coming across any sort of learning material. As good as that is for developers who are looking for a good way to host their app, for those of us who are coming at it from the IT Pro perspective it can add unnecessary complexity that it’s not especially desirable during the initial stages of learning… if the code I’m using as an example breaks on deployment, how do I know whether it’s Docker or the application at fault?
So my goal with this new blog series is to help outline the Docker platform from an infrastructure perspective so we can operate it more effectively and engineer solutions that will better help our developer cousins. What I will cover over the next few blog posts is how to create, run and destroy your containers, how to handle storage that exists beyond the container’s lifespan, how to connect it up to a network and what to expect from that, and how to deploy a container (or containers) in an automated fashion.
I’m won’t go into any major discussions on how to install Docker on your workstation or laptop; the official Docker documentation should be sufficient for our purposes (https://docs.docker.com/desktop/).
Let’s start simple. I’ve installed Docker Desktop 2.4 on my Mac and I’m going to edit my project files in VS Code (version 1.50.1 in my case). Here’s the step-by-step process: create a container image based on Ubuntu Linux and copy some files into it, then create a container from the image and connect into it using a bash prompt.
- Create a folder in your project folder to hold the dockerfile plus a subdirectory for the app (in my example, I’ve called my project folder dockerblog1 and added an app subfolder to that)
- In the app subfolder, add a file or two (it doesn’t matter what they are for now; I’ve added a hello world HTML file in this example)
- In your root folder, create an empty file and name it Dockerfile
- In Dockerfile, copy and paste the following:
Step 1: Specify the parent image for the new image
FROM ubuntu:latest
STEP 2: Configure work directory
WORKDIR /app
STEP 3: Copy website code to container
COPY ./app/. .
5. Run this to build the docker image (Note the trailing period to denote where to find the dockerfile): docker build –tag dockerblog1:1.0 .
DevMac:dockerblog1 kris$ docker build --tag dockerblog1:1.0 .
Sending build context to Docker daemon 3.584kB
Step 1/3 : FROM ubuntu:latest
---> 9140108b62dc
Step 2/3 : WORKDIR /app
---> Running in 5cb7b5810b99
Removing intermediate container 5cb7b5810b99
---> a905ac46d8c8
Step 3/3 : COPY ./app/. .
---> 2eab0b57bcc5
Successfully built 2eab0b57bcc5
Successfully tagged dockerblog1:1.0
6. Run docker image and go straight to bash inside the container, then list the contents of the /app folder and show the contents of the file we copied in:
DevMac:dockerblog1 kris$ docker run -it --entrypoint=/bin/bash dockerblog1:1.0
root@464366ad317a:/app# ls -al
total 12
drwxr-xr-x 1 root root 4096 Oct 9 22:47 .
drwxr-xr-x 1 root root 4096 Oct 9 22:49 ..
-rw-r--r-- 1 root root 22 Oct 9 22:43 helloworld.htm
root@464366ad317a:/app# cat helloworld.htm
Hello world!
7. Exit the bash prompt, which will terminate the container
root@464366ad317a:/app# exit
8. Run docker container ls -a to see all containers, even those that have exited (like the one we just created)
DevMac:dockerblog1 kris$ docker container ls -a
CONTAINERID IMAGE COMMAND CREATED STATUS PORTS NAMES
464366ad317a dockerblog1:1.0 "/bin/bash" 14 minutes ago Exited (0) 14 minutes ago charming_lovelace
9. To remove the container, run the following: docker container rm <container ID>
DevMac:dockerblog1 kris$ docker container rm 464366ad317a
464366ad317a
10. To remove the image, run the following: docker image rm <image:version>
DevMac:dockerblog1 kris$ docker image rm dockerblog1:1.0
Untagged: dockerblog1:1.0
Deleted: sha256:2eab0b57bcc5b86b97ecc9c01d5f31220728b365bd737dc4a78732be6250a283
Deleted: sha256:d8557f1e049e9b1c88618fabf99e28039ea622e6edd16eba50efdea57e8fe7b4
Deleted: sha256:a905ac46d8c8720d471921b6f72186f70fdb1e81074901b3e2a00493ce687eae
Deleted: sha256:16cd83332219aa83cbe7e5e636cfd07a06a8a62cc20727e6e81c3bf37faa86d4
There’s more than a few things to unpack from that process, which we’ll go into in a future blog post. But hopefully this has been a useful starting point for your own Docker experiments.
In the next post, we’ll dig into some of the steps we performed above so we can understand why we did them, why they’re useful and what can we change to make them better.