Skip to main content

Docker

Follow the installation instruction from Docker website in your system. Once docker service has started, you can check:

docker info

# or
docker version

List images:

docker images

Run an image:

docker run -ti ubuntu:latest bash
docker run <image-id>

-ti stands for terminal interactive. If the image is not present locally, it will pull from the docker hub. Alternatively, you can use docker pull to download locally an image prior to running.

List docker process:

# running containers
docker ps

# all containers
docker ps -a

# last exited container
docker ps -l

Create images from container:

docker commit <container-id>

Give a name to the image:

docker tag <SHA-256-image-id> <my-image-name>

We can assign name at the same time with commit:

docker commit <container-id> <image-name>

This will save the state of the container in the latest image.

Start a detached container:

docker run -d -ti ubuntu:latest bash

Attach running detached container:

docker attach <container-name-or-id>

Exit from the docker container without killing the process: [control] + [P], [control] + [Q]

Sharing volumes (shared folder with the host):

docker run -v /home/host/docs:/home -ti centos bash
docker run -v ${PWD}:/home -ti ubuntu bash

Check docker storage usage:

docker system df

Remove build cache:

docker builder prune

Delete container:

docker rm <id-or-name>

Delete all idle containers:

docker container prune

Delete images:

docker rmi <image-name>

Reclaim space immediately (otherwise it may take several minutes to reflect storage space after a cleanup operation):

docker run --privileged --pid=host --rm docker/desktop-reclaim-space

Delete all the stopped containers and images:

docker system prune -a

Run and remove when docker instance exits:

docker run --rm <image-name>

Use host network:

docker run -it --net=host centos bash

Port forwarding:

docker run -ti -p 8888:8888 -v ${PWD}:/home jupyter bash

Set MAC address:

docker run -it --mac-address 02:42:ac:11:0d:11 ubuntu bash

You can also pass environment variables with -e flag, e.g.,-e LANG=C.UTF-8, -e TZ=Asia/Singapore. You can pass multiple -e flags to pass multiple such variables.

Running GUI apps on docker

First we need to install a X-window system. On linux, we can choose X11. On macOS X-Quartz, on Windows xming. On macOS, allow connections from network clients:

x-quartz

After launching XQuartz (you may launch for terminal by open -a XQuartz), issue xhost +. More about X-window system here.

# macOS
docker run --rm -tid -e DISPLAY=docker.for.mac.host.internal:0 ubuntu firefox

# linux
docker run --rm -tid --net=host -e DISPLAY=:0 ubuntu firefox

# Windows
docker run --rm -tid -e DISPLAY=host.docker.internal:0 ubuntu firefox

I assumed you have the X version of firefox is installed in the ubuntu image.

Running apache on docker

Here we will install centos docker image:

docker pull centos

Run docker:

docker run -ti centos bash

Once inside centos update the os:

dnf up

Install apache:

sudo dnf install httpd
exit
docker commit <container-id> centos
docker run --net=host centos httpd -D FOREGROUND &

Now if you browse your host IP address you should be able to view the default website. We can stop the httpd, by killing the container.

docker ps
docker kill <container-id>

Stop all running containers:

docker stop $(docker ps -a -q)

Dockerfile

Write the Dockerfile:

# Start from Ubuntu 22.04 LTS
FROM ubuntu:jammy

# Update OS
RUN apt update \
&& apt upgrade -y

# Install software packages
RUN apt install -y python3 \
&& apt install -y python3-pip \
&& apt install -y git \
&& apt install -y fonts-open-sans

# Install pip packages
RUN pip3 install jupyterlab numpy scipy matplotlib

# bashrc settings
RUN echo 'alias jupyter-notebook="jupyter-notebook --allow-root --no-browser"' \
>> $HOME/.bashrc

# clone code from git repository
WORKDIR /root
RUN git clone https://github.com/pranabdas/arpespythontools.git

# leave in `/home` which we can map with the host
WORKDIR /home

Build docker image (the file is named Dockerfile):

docker build -t arptools .

If the file is named other than Dockerfile:

docker build -t arptools -f arptools.dockerfile .

Launch:

docker run -ti --net=host -v /host/path:/home arptools bash

Add non-root user and group:

RUN groupadd -r noroot && useradd -r -g noroot noroot

# make owner of certain directory / executables
RUN chown -R noroot:noroot build_dir

# set user
USER noroot

More details on adduser (also check useradd --help):

ENV NON_ROOT_USER="noroot"
ARG NON_ROOT_USER_PASSWORD="gf3r-trf5-6etd"
ENV NON_ROOT_USER_GROUP="noroot"

RUN groupadd -r $NON_ROOT_USER_GROUP -g 1000 \
&& useradd \
--uid 1000 \
--system \
--gid $NON_ROOT_USER_GROUP \
--create-home \
--home-dir /home/$NON_ROOT_USER/ \
--shell /bin/bash \
--comment "non-root user" \
$NON_ROOT_USER \
&& chmod 755 /home/$NON_ROOT_USER/ \
&& echo "$NON_ROOT_USER:$NON_ROOT_USER_PASSWORD" | chpasswd
tip

Running chown on a large directory may increase the image size significantly. In such case build the directory using another instance, and copy it to new image using:

COPY --chown=noroot:noroot /home/build_dir /noroot/build_dir

Docker hub

Login:

sudo docker login docker.io

Tag a local image:

sudo docker tag localimage:latest username/localimage:latest

Push a local image:

sudo docker push username/localimage:latest

Transferring image offline

docker pull ubuntu
docker save -o ubuntu_image.docker ubuntu
docker load -i ubuntu_image.docker

Docker compose

Docker compose can help create, run, and manage the lifecycle of the containers. For example below docker run command

docker run -d --name apache -p 8080:80 -v ${PWD}/build:/usr/local/apache2/htdocs/ httpd:latest

would translate to following docker compose specification:

compose.yaml
services:
apache:
image: httpd:latest
container_name: apache
ports:
- '8080:80'
volumes:
- ./build:/usr/local/apache2/htdocs

Now go to the directory where compose.yaml is saved and issue:

docker compose up

Now we can access our website at localhost:8080 using a web browser.

We can run a service in the background with -d (detached) flag.

docker compose up -d

Once we are done, we can stop or down (down stops the container and removes the container).

docker compose stop
docker compose down

Explore more docker compose commands with

docker compose --help

How can we access the shell of a container running a service? List running containers:

docker ps

Then access the shell:

docker exec -it <container-id> bash

Use systemctl in docker

See this project: docker-systemctl-replacement.

References