Build and run your first Docker container

Overview

Teaching: 20 min
Exercises: 20 min
Questions
  • How can I use Docker to run a container?

  • How do I create an image from scratch?

  • How can I share an image between systems?

  • Is Docker the only tool for building containers?

Objectives
  • Learn the basics of Docker including pull, run, build and push

  • Learn how to build an image using a Dockerfile

  • Practice with an advance example

Intro to Docker

Pulling and running an existing image

Pull a public image such as ubuntu or centos using the docker pull command. If a tag is not specified, docker will default to “latest”.

docker pull ubuntu:22.10

Now run the image using the docker run command. Use the “-it” option to get an interactive terminal during the run. Try some commands, then exit to leave the container.

docker run -it ubuntu:22.10
whoami
cat /etc/os-release
exit

Creating and building a Dockerfile

While manually modifying and committing changes is one way to build images, using a Dockerfile provides a way to build images so that others can understand how the image was constructed and make modifications.

A Dockerfile has many options. We will focus on a few basic ones (FROM, LABEL, ADD, and RUN)

Start by making an empty directory.

mkdir mydockerimage
cd mydockerimage

Create a simple shell script called hello in your local directory using your favorite editor.

#!/bin/bash
echo "Hello World! -- Me"

Now create a file called Dockerfile in the same directory like the following. Use your own name and e-mail for the maintainer label.

FROM ubuntu:22.10
LABEL maintainer="patsmith patsmith@patsmith.org"

ADD ./hello /bin/hello
RUN chmod a+rx /bin/hello

Now build the image using the docker build command. Be sure to use the -t option to tag it. Tell the Dockerfile to build using the current directory by specifying .. Alternatively you could place the Dockerfile and script in an alternate location and specify that directory in the docker build command.

docker build -t hello:1.0 .

Try running the image and run the hello script in the container. Exit when you are done.

docker run -it hello:1.0
hello
exit

Pushing a Dockerfile to dockerhub (optional)

Docker provides a public hub that can be use to store and share images. Before pushing an image, you will need to create an account at Dockerhub. Go to https://cloud.docker.com/ to create the account. Once the account is created, push your test image using the docker push command. In this example, we will assume the username is patsmith. If you haven’t done a docker login you may need to do that first.

docker tag hello:1.0 patsmith/hello:1.0
docker login
docker push patsmith/hello:1.0

The first push make take some time depending on your network connection and the size of the image.

Hands on Activity: MPI hello world

Now that you’ve practiced loading a simple script, try creating an image that can run this short MPI hello word code:

// Hello World MPI app
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv) {
    int size, rank;
    char buffer[1024];

    MPI_Init(&argc, &argv);

    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    gethostname(buffer, 1024);

    printf("hello from %d of %d on %s\n", rank, size, buffer);

    MPI_Barrier(MPI_COMM_WORLD);

    MPI_Finalize();
    return 0;
}

Hints:

  • You can start with the image “ecpe4s/ubuntu20.04:latest”. It already has MPI installed.
  • You compile with “mpicc helloworld.c -o /app/hello”

Solution

Dockerfile:

# MPI Dockerfile
FROM ecpe4s/ubuntu20.04:latest

ADD helloworld.c /app/

RUN cd /app && mpicc helloworld.c -o /app/hello

Now we build the image

docker build -t mydockerid/hellompi:latest .
docker push <mydockerid>/hellompi:latest

Log into the image and run the app:

docker run -it mydockerid/hellompi:latest
root@982d980864e5:/# mpirun -n 10 /app/hello
hello from 3 of 10 on 982d980864e5
hello from 4 of 10 on 982d980864e5
hello from 7 of 10 on 982d980864e5
hello from 9 of 10 on 982d980864e5
hello from 2 of 10 on 982d980864e5
hello from 5 of 10 on 982d980864e5
hello from 8 of 10 on 982d980864e5
hello from 0 of 10 on 982d980864e5
hello from 6 of 10 on 982d980864e5
hello from 1 of 10 on 982d980864e5

Surprise: It was Podman all along

Podman is a drop in replacement for Docker. We have replaced docker with podman on the training systems and aliased docker to podman. Podman is configured with reduced privileges which provides improved security since this doesn’t require running a daemon and doesn’t require extra privileges requires with a typical Docker installation.

(base) [tutorial@ip-172-31-3-250 ~]$ docker --version
podman version 3.0.1

Key Points

  • Docker handles the entire workflow from build to execution.

  • A Dockerfile is a recipe for how to create an image.

  • Podman is a drop in replacement for Docker.