Skip to content
Aaron Powell edited this page Aug 23, 2017 · 4 revisions

Welcome to the exercises from my Docker, FROM scratch talk. You'll find each exercise is tagged in the git repository using step-* to step through, and each step is a progression on the last one. (Almost) All of the steps will use run.bat in the root of the git repo, so this is obviously intended to run on Windows (using Linux containers though), if you're on a non-Windows OS you'll need to pull the commands out of the run.bat file.

Here we'll explain each step and the intended run sheet from the talk.

Step 1 - Hello World

Goal: Start a basic container from an Ubuntu image.

You'll be dropped into an interactive Ubuntu container running /bin/bash.

Exercises

  • Run ls to see what's on the file system
  • Run mkdir /foo to make a new folder at the root of the container
  • On the Host run docker ps and see the running container
  • On the container run exit to stop the process and shutdown the container
  • On the Host run docker ps and see the container isn't listed, add a --all flag to see the stopped container
  • On the Host run docker start <container id> to start the container
  • On the Host run docker attach <container id> to connect back into the container
  • On the container run ls / and see that the /foo folder is still there

Step 2 - Multiple containers from the same image

Goal: Start multiple containers that run in isolation of each other, and will remove themselves when stopped.

You'll start three containers, ubuntu1, ubuntu2 and ubuntu3, all detached.

Exercises

  • Start three terminals and run docker attach ubuntu1/2/3 in each to connect to each container
  • Pick a container and run mkdir /foo on it
  • On a different container run ls, the /foo directory won't exist
  • On the Host run docker stop ubuntu2
  • On the Host run docker ps --all and ubuntu2 is no longer listed

Step 3 - Volume mounting

Goal: Learn how to mount a volume into a running container

Note: If you're on a non-Windows OS you'll need to change %CD% to your OS's approach of getting the current working directory.

Exercises

There are no explicit exercises here other than running the docker run command and observing the output.

Step 4 - Single process containers

Goal: Run a single process in a container

Exercises

Note: You're dropped into a Node.js REPL, not /bin/bash.

  • Run console.log('Hello World');
  • Run const fs = require('fs'); fs.readdir('/', (err, paths) => console.log(paths)); and see the file system info

Step 5 - Run a node.js webserver

Goal: Run an application in a node.js container

Note: If you're on a non-Windows OS you'll need to change %CD% to your OS's approach of getting the current working directory.

Exercises

  • (After the container is started) On the Host run curl http://localhost:3000 to get the response from the webserver
    • This will result in an error, that's expected
  • On the Host run docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' node
    • No port bindings are listed

Step 6 - Run a node.js webserver with port binding

Goal: See how we can use port bindings from host to container.

Note: If you're on a non-Windows OS you'll need to change %CD% to your OS's approach of getting the current working directory.

Exercises

  • (After the container is started) On the Host run curl http://localhost:8080 to get the response from the webserver
  • On the Host run docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' node
    • See that the port 3000 on tcp in the container is bound to 8080 on the host

Step 7 - Creating images

Goal: Introduce the Dockerfile and create an image.

Exercises

  • Open the Dockerfile in an editor
    • Inspect the different commands in the Dockerfile, see the reference to understand them
  • On the Host run docker images
    • There is a new image called nodejs-app which we just created
  • On the Host run docker ps and see the node container uses the nodejs-app image

Step 8 - Intro to docker-compose

Goal: Introduce docker-compose for defining environments.

Exercises

  • Open the docker-compose.yml in an editor
    • Inspect the different parts of the file relative to the docker run commands, see the reference to understand it

Step 9 - Combining docker-compose and Dockerfile

Goal: See how we can combine docker-compose and a Dockerfile

Exercises

  • See the differences in the docker-compose.yml now that we use the Dockerfile

Step 10 - Environment variables

Goal: Learn about environment variables in docker.

Exercises

  • Open a SQL Server management tool (LINQPad, SQL Server Management Studio, etc.) and connect using sa and the password from the environment variable

Step 11 - Composing an environment

Goal: Using a compose file to represent multiple services that talk to each other

Note: This step assumes you have access to Visual Studio 2017

Exercises

  • Set the docker-compose project to the startup project in Visual Studio and launch
  • In your browser register a new account
  • Open a SQL Server management tool (LINQPad, SQL Server Management Studio, etc.) and connect using sa and the password from the environment variable
  • In your browser apply the EF migrations
  • Refresh your SQL explorer and see the new DB was created

Step 12 - Hiding the SQL server

Goal: Using a compose file to represent multiple services that talk to each other, but without port binding SQL

Note: This step assumes you have access to Visual Studio 2017

Exercises

  • Set the docker-compose project to the startup project in Visual Studio and launch
  • In your browser register a new account
  • In your browser apply the EF migrations
  • Open a SQL Server management tool (LINQPad, SQL Server Management Studio, etc.) and connect using sa and the password from the environment variable, which will timeout
  • On the Host run docker network ls and find the two networks created by the compose file, they are suffixed _web and _db
  • Run an interactive container with ubuntu and connect to the _db network
    • docker run -it --rm --network <network name> Ubuntu /bin/bash
  • Install ping in the container
    • apt-get update && apt-get install iputils-ping -y
  • Ping the SQL server using its network alias
    • ping sql
  • Run an interactive container with ubuntu and connect to the _web network
    • docker run -it --rm --network <network name> Ubuntu /bin/bash
  • Install ping in the container
    • apt-get update && apt-get install iputils-ping -y
  • Ping the SQL server using its network alias (which will timeout)

Step 13 - FROM scratch

Goal: Create a docker image that uses the scratch base image.

Exercises

No exercises, just running a Go lang app in the smallest image possible!

Step 14 - Multi-stage Dockerfiles

Goal: Combine build and app into a single Dockerfile

Exercises

There's no explicit exercise, just a reformatted Dockerfile that has a build image created and then the application image.