Skip to main content

Docker & Docker Compose Commands

3064 words·
Docker Docker-Compose Commands Systemd Service Units Ansible-Playbook
Table of Contents

Install Docker
#

Installation Script
#

Note: This scripts install the Docker CE Community Edition, this is the version provided directly by Docker.

Ubuntu Script

Install Docker and Docker-Compose (apt)

#!/bin/bash

# Install Docker and Docker Compose on Ubuntu

sudo apt-get update

sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
Debian Script

Install Docker and Docker-Compose (apt)

#!/bin/bash

# Install Docker and Docker Compose on Debian

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
Raspberry Pi 5 64-bit (Debian ARM) Script

Install Docker and Docker-Compose (apt)

#!/bin/bash

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
# REF:
https://docs.docker.com/engine/install/debian/#install-using-the-repository 
  • Create / run script
# Create file and insert script
vi docker_setup.sh

# Change file mode to executable
chmod +x docker_setup.sh

# Run installation script
./docker_setup.sh

# Check Docker Version
docker --version
  • Add user to Docker group

Some Linux distributions do not automatically create a Docker group. Create a Dockergroup if it does not yet exist, Docker will bind to this group.

# Create Docker group (Ubuntu does this by default)
sudo groupadd docker


# Add user to Docker group: RedHat, Ubuntu
sudo usermod -aG docker username

# Add user to Docker group: Debian
sudo adduser username docker

Ansible Playbook
#

  • Ubuntu Version
---
- name: Install Docker on Ubuntu
  hosts: all
  become: true
  tasks:
    - name: Update apt
      apt:
        update_cache: yes

    - name: Install dependencies
      apt:
        name: ca-certificates,curl,gnupg,lsb-release
        state: present

    - name: Create Docker keyring directory
      file:
        path: /etc/apt/keyrings
        state: directory

    - name: Add Docker GPG key
      shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

    - name: Add Docker repository to apt sources
      shell: echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

    - name: Update apt again
      apt:
        update_cache: yes

    - name: Install Docker
      apt:
        name: docker-ce,docker-ce-cli,containerd.io,docker-buildx-plugin,docker-compose-plugin
        state: present

    - name: Add ubuntu user to docker group
      user:
        name: ubuntu
        groups: docker
        append: yes

Docker Compose Overview
#

Docker Compose Commands
#

Depending on the Docker Version start the command with either docker-compose for the old version, or docker compose for the new version.

# Check Docker Compose Version
docker compose version
  • Test yml syntax
# Check the yml syntax without starting the Container
docker compose config

# Check the yml syntax without starting the Container: Quiet (Dont list the yml file to shell)
docker compose config -q
  • Pull image
# Pull latest Image (Stop Container first)
docker compose pull
  • Create, start & stop containers
# Start Containers
docker compose up -d

# Start only a specific service / container from docker compose file
docker compose up -d servicename

# Start Containers: Custom filename
docker compose -f filename.yaml up -d


# Stop Containers
docker compose down

# Stop Containers: Custom filename
docker compose -f filename.yaml down


# Restart Containers
docker compose restart
  • Start & stop specific container / service from the Docker Compose stack
# Start, stop, restart, pause & unpause a Docker Container
docker compose start servicename
docker compose stop servicename
docker compose restart servicename
docker compose pause servicename
docker compose unpause servicename
  • Logs
# List Logs till Command execution
docker compose logs

# List Logs all logs (running) 
docker compose logs -f
  • List Docker Containers
# List (only) Containers from Docker Compose file
docker compose ps

# List processes running inside each Container
docker-compose top

Docker Project Name
#

Note: Docker Compose generates a default project name based on the name of the directory where the docker-compose.yml file is located. This project name is then used as a prefix for network names and container names.

# Create environment file
sudo vi .env

# .env
COMPOSE_PROJECT_NAME=name-of-the-stack

Depends On
#

Define the order in which services are started up.

version: "3.9"
services:
  web:
    build: .
    depends_on:
      - db # Wait for db Service
      - redis # Wait for Redis Service
  
  redis:
    image: redis

  db:
    image: postgres

Container Image Tag
#

Go to hub.docker.com to find the latest image tags. Use a colon to define the image tag after the image, for example:

version: '3'

services:
  app:
    container_name: upload_nextcloud:25.0.5-apache

Or just the define the image with the latest tag, to automatically pull the latest version of the image, for example:

version: '3'

services:
  app:
    container_name: upload_nextcloud:latest

Networking
#

Note: Docker Compose generates a default project name based on the name of the directory where the docker-compose.yml file is located. This project name is then used as a prefix for the internal Docker network names.

Overview
#

# Create new external Docker network
sudo docker network create external-network-1

# List Docker networks
sudo docker network ls
version: "2.4"
services:
  db:
    image: ...
    ...
    networks:
      - internal-network-1 # Define the internal Docker stack network

  docker-app:
    depends_on:
      - db
    image: ...
    ...
    networks:
      - internal-network-1 # Define the internel Docker stack network
      - external-network-1 # Define external reverse proxy network

networks:
  external-network-1: # Define external reverse proxy network
    external: true
  internal-network-1: # Define internal Docker stack network

Custom Subnet
#

# Create new external Docker network: With custom subnet
sudo docker network create --subnet=192.168.11.0/24 external-network-2
version: "2.4"
services:
  db:
    image: ...
    ...
    networks:
      - internal-network-1 # Define the internal Docker stack network

  docker-app:
    depends_on:
      - db
    image: ...
    ...
    networks:
    networks:
      internal-network-1: # Define the internel Docker stack network
      external-network-2: # Define external reverse proxy network
        ipv4_address: 192.168.11.11 # Define IP address


networks:
  external-network-2: # Define external reverse proxy network
    external: true
  internal-network-1: # Define internal Docker stack network

Ports
#

  • Example: Expose port to container network only

This means port “443” is exposed to other containers within the same Docker network but not mapped to the host’s port 443.

version: "3.9"
services:
  web:
    ports:
      - "443"
  • Example: Bind port to specific interface

Container port “443” is only exposed to the host interface with the IP “192.168.30.90”.

version: "3.9"
services:
  web:
    ports:
      - "192.168.30.90:443:443"

Environment File
#

Use environment variables defined in an external file

# Create environment file
sudo vi .env
version: "2"
services:
  docker-app:
    image:
    container_name:
    env_file: # Define external environment file
      - .env

DNS & Hosts
#

  • Define host entry in Docker Compose file
version: "2"
services:
  docker-app:
    image:
    container_name:
    extra_hosts:
      - "host1.jklug.local:192.168.30.31" # Define host entry
      - "host2.jklug.local:192.168.30.32"
  • Define DNS serer in Docker Compose file
version: "2"
services:
  docker-app:
    image:
    container_name:
    dns:
      - 1.1.1.1 # Define DNS server
      - 8.8.8.8

Dockerfile
#

Build and create container from cutom image define in Dockerfile

version: '3.9'
services:
  app:
    build:
      context: ./ # Path to Dockerfile
      dockerfile: Dockerfile
    image: image-name:tag # Define image name and tag
    container_name: container-name # Define container name
    restart: unless-stopped
    hostname: hostname # Define host name
    ports:
      - 8080:80

Docker Volumes
#

Standard Docker Volume
#

version: "3.9"
services:
  application:
    image: image:latest
    working_dir: /app
    volumes:
      - application_data:/app

volumes:
  application_data:

Docker Volume Defined Location
#

version: '3.9'
services:
  application:
    image: image:latest
    volumes:
      - application_data:/data

volumes:
  application_data:
    driver: local
    driver_opts:
      type: none
      device: /opt/app/application_data
      o: bind

Host Mapping
#

version: "3.9"
services:
  application:
    image: image:latest
    working_dir: /app
    volumes:
      - "./application_data:/app"

Note: Depending on the necessary permissions inside the container, it’s necessary to create the folder on the host with the required permissions before the container is started.


Working Directory & Commands
#

This is the directory where the container will start, and it’s where commands defined with CMD in the Dockerfile, or commands specified in the Docker Compose file under command or entrypoint, will be executed.

version: "3.9"
services:
  application:
    image: image:latest
    working_dir: /app
    volumes:
      - application_data:/app
    command: ["/bin/sh", "-c", "while :; do sleep 10; done"]


volumes:
  application_data:

Systemd Service Units
#

Create Service Unit vi /etc/systemd/system/docker-compose-example.service

[Unit]
Description=Docker Compose Service
Requires=docker.service #Requires Docker service
After=docker.service #Start after Docker service

[Service]
Type=oneshot #Service exits after the ExecStart command completes
WorkingDirectory=/home/ubuntu/docker-compose/
ExecStart=/usr/bin/docker compose -f /home/ubuntu/docker-compose/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /home/ubuntu/docker-compose/docker-compose.yml down
StandardOutput=syslog
SyslogIdentifier=docker-compose-example
RemainAfterExit=yes #Service considered active after its process exits

[Install]
WantedBy=multi-user.target #Service is started during system startup process

Reload the systemd daemon to load the new service unit:
systemctl daemon-reload

Enable service to start on boot:
systemctl enable docker-compose-example.service

Start the service & start the containers defined in Docker-Compose file:
systemctl start docker-compose-example.service


Docker Overview
#

Docker Version
#

# Check Docker Version
docker version

# Check Docker Compose Version
docker compose version

Docker Images
#

Dockerhub: https://hub.docker.com/

Note when no Image tag is defined, the “latest” tag is used.

# Login to Dockerhub
docker login

# Pull Image from Dockerhub
docker pull image-name

# List Docker Images
docker images ls

# Delete Docker Image
docker image rm Image-ID

# Create Image from Container
docker container commit container-name image-name:tag

# Create Image from Container: Set Author and Commit Message
docker container commit -a "Author Name" -m "Commit message" container-name image-name:tag

# List history (commands) from Image
docker history image-name:tag

Create & Run Container
#

# Create & start Container
docker run --name Container-name Image-name

# Create & start Container: Detached
docker run -d --name Container-name Image-name

# Create / start Container: Bind Port
docker run -d -p8080:80 --name Container-name Image-name


# Create / start Container: Line break
docker run -d \
-p 8080:80 \
--name Container-name \
--mount source=Volume-name,target=/vol \
--net Network-name \
--restart unless-stopped \
image # Define Container image


# Create / start Container: Restart Policy
docker run -d --restart always Image-name
--restart always
--restart unless-stopped
--restart no

# Update Restart Policy from running Container
docker update --restart unless-stopped ContainerID

# Keep Container runing in the background (Debug)
docker run -dt Container-name . sleep infinity


# Rename Container
docker rename container-name new-container-name

Start & Stop Container
#

# Start Container
docker start Container-ID

##Start several Containers at once
docker start Container-ID &&
docker start Container-ID

# Stop Container
docker stop Container-ID`

# Immediately stop Container
docker kill Container-ID

# Restart Container
docker restart Container-ID


# List running Containers
docker ps

# List running and stopped Containers
docker ps -a # or
docker ps --all

Delete Stopped Container
#

# List running & stopped Containers
docker ps -a

# Delete stopped Container
docker rm Container-ID

Docker PS - Format Output
#

This command is very useful in environments with lots of running containers, it provides a more manageable overview.

# List ID's, Names & Image Versions
docker ps --format '{{ .ID }}\t{{.Names}}\t{{ .Image }}'

# List ID's, Names & Ports
docker ps --format '{{ .ID }}\t{{.Names}}\t{{ .Ports }}'

# List ID's, Names & Uptime
docker ps --format '{{ .ID }}\t{{.Names}}\t{{.Status}}'

# List ID's, Names & Creation Time
docker ps --format '{{ .ID }}\t{{.Names}}\t{{.RunningFor}}'

# List ID's & Names
docker ps --format '{{ .ID }}\t{{.Names}}'

# List only ID's
docker ps --format '{{ .ID }}'


# Save Docker PS output into file
docker ps | sort > /path/to/file

Container Logs
#

# Follow logs of specific container
docker logs -f container_id_or_name

# Follow logs of docker compose stack
docker compose logs -f

List Container Environment Variables
#

# List environment variables set in the container
docker exec -it container-name env

Execute Internal Terminal
#

Depending on the base image used for a container, bash is not always available. Here are some alternatives:

# Open shell inside Container
docker exec -it Container-ID /bin/bash
docker exec -it Container-ID bash
docker exec -it Container-ID ash
docker exec -it Container-ID sh

# Open shell inside Container: Define user
docker exec -it -u www-data Container-ID bash

# Exit Internal Terminal
exit

Run Command inside Container

# List Container directory / print to host shell: Without interactive TTY
docker exec container-name ls /app

Copy files from / to Container
#

# Copy file from Container to host
docker cp ContainerID:/container/path /host/path

# Copy file from host to Container
docker cp /host/path/ ContainerID:/container/path

Container Changes
#

# List changes made inside a Container
docker diff container-name

A Added
C Changed
D Deleted

Import & Export Images
#

Export Container, Import Image from Container

# Export stopped Container to tar file
docker export Container-ID > container-name.tar

# Import Image from exported Container
docker import - container-name < container-name.tar

Export & Import Image

# Export Docker Image
docker save -o image-name.tar image-name:tag

# Import Docker Image
docker load -i image-name.tar # or
docker load < image-name.tar

Docker Inspect
#

List Container Details

# List Container Details
docker container inspect Container-Name

# Grep Container IP
docker inspect Container-ID | grep IPAddress

List Image Details

# List Image Details
docker inspect image-name:tag

# Grep Image Author
docker inspect image-name:tag | grep "Author"

Docker Network
#

When not otherwise defined all Containers start in the default bridge network. Containers can communicate with each other using Container names as their DNS addresses.

Docker Network Commands:

# List Networks
docker network ls

# Inspect Network: E.g bridge
docker network inspect bridge

# Create Docker Network
docker network create network-name

# Delete Docker Network
docker network rm network-name


# Connect Container to Network
docker network connect network-name Container-ID

# Disconnect Container to Network
docker network disconnect network-name Container-ID

Start Container in specific network:

# Start container in specific network: e.g nginx
docker run --net network-name --name container-name -d nginx 

# Start container in specific network, define custom IPv4 address:
docker run --net network-name --ip 192.168.60.11 --name container-name -d nginx 

Dockerfile
#

Dockerfile Commands

FROM # Define base Image for Container
FROM ubuntu # Example

WORKDIR # Define working directory for RUN, CMD, ENTRYPOINT, COPY & ADD instructions 
WORKDIR /app # Example

COPY # Copy files from host into Container WORKDIR
COPY . . # Example

PULL # Adds files from Docker repository

RUN # Execute shell
RUN apt-get update # Example

CMD # Run Command (can only be used once)
CMD ["echo", "Hi there"] # Example

EXPOSE # Expose Port
EXPOSE 80 # Example

Docker Build
#

Create & Start Image from Dockerfile

# Build Image from Dockerfile
docker build .

# Build Image from Dockerfile: Define image name
docker build -t image-name .

# Start Container from image
docker run --name container-name image-name
# The Container image looks as follows: List images
docker image ls

# Shell output
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
image-name   tag       34ac7f7fb9ce   About a minute ago   265MB
# The running Container looks as follows: List running containers
docker ps

# Shell output
CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                                             NAMES
1fb84ec5e41f   image-name:tag   "docker-entrypoint.s…"   9 seconds ago   Up 7 seconds   3000/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp   container-name

Open the Container terminal with docker exec -it container-name ash and check the hostname with hostname.


Container Registry
#

Authenticate
#

# Authenticate to the registry: DockerHub
docker login

# Authenticate to the registry: Define Server and port
docker login registry.example.com:5000
# Credential file
~/.docker/config.json

Image Name
#

In order to push a local image to the registry, the image name must be in the following format: My-Docker-ID/Imagename

# Tag an existing image with a new name or tag
docker image tag source-image My-Docker-ID/target-image

Push & Pull
#

# Push image to DockerHub
docker image push My-Docker-ID/Imagename

# Run image from DockerHub
docker container run My-Docker-ID/Imagename

Docker Volumes
#

# Create Docker Volume
docker volume create volume-name

# Delete Docker Volume
docker volume rm volume-name

# Delete all Docker Volumes that are not mounted
docker volume prune

# List Docker Volumes
docker volume ls

# Inspect Docker Volume
docker volume inspect volume-name

# Inspect Docker Volume: Shell Output
[
    {
        "CreatedAt": "2023-06-02T19:39:29Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/volume-name/_data",
        "Name": "volume-name",
        "Options": null,
        "Scope": "local"
    }
]

Change Docker Directory
#

# Default Docker directory
/var/lib/docker/
# Stop Docker
sudo systemctl stop docker

# Open Docker configuration file
sudo vi /etc/docker/daemon.json

# Define data root
{
  "data-root": "/new/path/to/docker-data"
}

# Move data
sudo mv /var/lib/docker /new/path/to/docker-data

# Start Docker
sudo systemctl start docker
# Verify changes
docker info | grep "Docker Root Dir"

Trouble-shooting
#

When the Docker service itself want start it can be very helpful to output the following logs:

dockerd --debug Show Docker logs

It could also be helpful to check your /etc/docker/daemon.json configuration.


Clean Up
#

Docker Prune
#

# Remove dangling (not tagged) images
docker image prune

# Remove unused and dangling (not tagged) images
docker image prune --all

# Remove unused and dangling (not tagged) image: (Do not prompt for confirmation)
docker image prune --all --force
# Remove all stopped containers
docker container prune

# Remove unused networks
docker network prune

# Remove unused volumes
docker volume prune
# Remove all stopped containers, unused networks, and unused volumes 
docker system prune

# Remove all unused data (containers, networks, volumes, and images)
docker system prune -a

Delete All Resources
#

# Stop all Contrainers
docker kill $(docker ps -q)

# Delete all Containers
docker container rm -f $(docker container ls -aq)

# Delete all Volumes
docker volume rm -f $(docker volume ls -q)

# Delete all Images
docker image rm -f $(docker image ls -q)

# Delete all Dockernetworks
docker network prune -f

Stop & Delete at once:

docker kill $(docker ps -q)  &&
docker container rm -f $(docker container ls -aq) &&
docker volume rm -f $(docker volume ls -q) &&
docker network prune -f

Delete Docker
#

When the docker services want start and nothing else helps, sometimes the fastest way to solve the problem is to reinstall docker. To do so, first stop the docker service and uninstall all docker services.

Remove Docker Explanation
systemctl stop docker.service Stop Docker Service
sudo apt remove docker-ce docker.io docker Remove Docker

Also it could be necessary to delete the following Docker directories:
/var/lib/docker/
/run/docker.pid
/run/docker.sock

After everything is removed use the script provided at the top of this tutorial to reinstall Docker.


Links #

# Docker Compose Versions
https://docs.docker.com/compose/compose-file/compose-versioning/