Monthly Archives: August 2024

[0x17] Docker Intro Workshop Notes

Yesterday we had another instance of the Docker Intro workshop. Here are some notes on what we did.

You can find the slides for the workshop here: https://tantemalkah.at/2024/docker-intro

While the Docker Handbook by Farhan Hasin Chowdhury is great overall introduction to Docker, including setup and concept explanations, the Play with Docker classroom has many interactive tutorials, where you can neatly try out stuff on the side (right there in the browser, if you are logged in with a Docker Hub account – but you can do the same thing on your own machine, if you have Docker already running).

We specifically went through the Docker for Beginners – Linux lab, and here is a slightly adapted quick run-through version:

# clone the repo containing the demo app we'll run in a
# container later
git clone  https://github.com/dockersamples/linux_tweet_app
ls -l linux_tweet_app/

# check the hostname of a plain alpine linux container
docker run alpine hostname
# see all (also stopped) containers
# shortcut for: docker container ls --all
docker ps -a
# and now delete the unused alpine container
docker rm gifted_brown  # use the name from docker ps output

# run a bash (interactively) in a fresh ubuntu container
# (and remove it automagically after it stops)
docker run -it --rm ubuntu bash
# while the bash in the container is running you can check
# its status in another terminal
docker ps
# and after it is stopped it should be completely gone
docker ps -a

# run a MySQL container with a randomly generate root password
# (in detached mode, so it does not block your terminal)
docker run --rm --detach --name mysql \
  -e MYSQL_ROOT_PASSWORD=AZ2NchuaP149fmNRxqh1cmU0Mxg815Bg \
  mysql:latest
docker ps
# see the latest logs of the mysql container
docker logs mysql 
# output logs in "follow" mode (so log display keeps running)
# (if you want to quit the logs command again, type CTRL+C)
docker logs -f mysql
# see what processes are running in the mysql container
docker container top mysql 
# while the container is still running, execute another
# command in it, e.g. the mysql client to (the first "mysql"
# is the containter name, the second the actual "mysql"
# command, followed by its arguments) 
docker exec -it mysql mysql -u root -p -v
# in a separte terminal you can see that only one mysql
# container is running
docker ps

# now let's build an image for the demo app
cd linux_tweet_app/
cat Dockerfile 
docker image build --tag linux_tweet_app:1.0 .
docker images

# now we can run the demo app and map its port 80 to
# 1234 on the host
docker run -d -p 127.0.0.1:1234:80 \
  --name linux_tweet_app linux_tweet_app:1.0
docker ps
docker container stop linux_tweet_app 
docker rm linux_tweet_app

# now we run it with a mount, so we can change its html files
# directly from our host, without the need to go into the
# container and change it there
docker run --rm -d --publish 127.0.0.1:1234:80 \
  --name linux_tweet_app \
  --mount type=bind,source="$(pwd)",target=/usr/share/nginx/html \
  linux_tweet_app:1.0
docker ps
ls -l
# let's change something in the index.html file
# if you are not familiar with vim, you can also use nano or
# open the file in the file browser with your GUI editor
vim index.html
# now take a look at http://localhost:1234 to see the changes

# even if we stop (and implicitly remove) the container to
# start a fresh one, your changes are still persisted, 
# because they are now not saved in the container but in
# your mounted linux_tweet_app dir
docker stop linux_tweet_app 
docker run --rm -d --publish 127.0.0.1:1234:80 \
  --name linux_tweet_app \
  --mount type=bind,source="$(pwd)",target=/usr/share/nginx/html  \
  linux_tweet_app:1.0

One thing I want to mention here specifically is port mappings. In most tutorials and explanations, sometimes even in the official Docker docs, you will find port mappings like -p 1234:80, mapping the port 80 inside the container (where e.g. a web app is running) to the port 1234 on your host machine (so you can access it through http://localhost:1234). This is all fine, and maybe just the thing you want on the final production server (because somehow your visitors from the interwebs should be able to access the page inside the container – probably not on port 1234 though). But while developing and testing locally, you might have a security issue there. Because mapping -p 1234:80 means that the port 1234 is opened on ALL your interfaces. So whoever is on the same local network as you and has your IP address can also access your web app. But while developing or testing on your local machine, you might not have all required security measures in place. So the safer default is always to map it to your local port ONLY on your loopback interface (which is 127.0.0.1, the actual „localhost“). So instead of the above, use -p 127.0.0.1:1234:80. This way really only you (or anyone who already is on your machine) can access the web app inside the container.

In the end we also took a quick look at compose files and how they can be used to spin up a range of services. But as usual, time was way to short to get into everything in details. The general idea was that participants now have a good entrypoint (like every container needs), to continue exploring the Docker lands.

Here are also a few more resources to continue your journey (apart from the Docker Handbook and the Play with Docker classroom):