Operations 25 min read

Master Dockerfile and Docker‑Compose: Build Custom Images and Orchestrate Containers

This guide explains how Docker images are built with Dockerfile, covers all basic instructions such as FROM, LABEL, RUN, WORKDIR, ADD, COPY, ENV and CMD, shows a complete example of creating a custom Django image, and then introduces Docker‑Compose for multi‑container orchestration with installation steps and common commands.

Raymond Ops
Raymond Ops
Raymond Ops
Master Dockerfile and Docker‑Compose: Build Custom Images and Orchestrate Containers

Dockerfile Image Creation

In Docker or Podman, an image is the foundation of a container. When official images from Docker Hub cannot meet business needs, a custom image must be built using a Dockerfile.

A Dockerfile is a plain‑text file that contains a series of instructions, each creating a new layer in the image. Fewer instructions produce smaller images.

Basic Instructions

FROM – specifies the base image (only one per Dockerfile).

LABEL – adds metadata such as version or maintainer.

RUN – executes shell commands inside the image; combine multiple commands with && or line‑continuation \ to avoid extra layers.

WORKDIR – sets the working directory (similar to cd).

ADD – copies files from the host and can automatically extract archives.

COPY – copies files or directories without extraction.

ENV – defines environment variables.

CMD – the default command executed when a container starts (can be overridden).

Example: Build a Django Image

mkdir /home/docker && cd /home/docker
touch Dockerfile run.sh sources.list
# edit sources.list to use a domestic Ubuntu mirror
# download Django source
wget -O Django-3.2.5.tar.gz https://gitee.com/mirrors/django/archive/3.2.5.tar.gz
# Dockerfile content (simplified)
FROM ubuntu:20.04
LABEL version="3.2.5" maintainer="[email protected]"
ADD Django-3.2.5.tar.gz /opt/
COPY sources.list /etc/apt/sources.list
RUN apt update && apt install -y python3 python3-pip
WORKDIR /opt/
RUN mv django-3.2.5 django
WORKDIR /opt/django
RUN python3 setup.py install
WORKDIR /opt
RUN django-admin.py startproject djdemo
COPY run.sh /opt/djdemo/run.sh
WORKDIR /opt/djdemo
RUN sed -i "s/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = \['*'\]/g" djdemo/settings.py && chmod 755 run.sh
EXPOSE 8000
CMD ["/bin/sh", "run.sh"]
# run.sh content
python3 manage.py runserver 0.0.0.0:8000
# Build and run
sudo docker build -t djdemo:3.2.5 .
docker run -d -p 8008:8000 --name=django1 djdemo:3.2.5

After building, the new image can be listed with docker images and run with port mapping.

Docker‑Compose Container Orchestration

Docker‑Compose lets you define multiple services in a single docker-compose.yml file and manage them as a project.

Installation

# Linux example
sudo curl -L "https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Check version with docker-compose version. Remove with

sudo rm /usr/local/bin/docker-compose /usr/bin/docker-compose

.

Common Commands

docker-compose up [-d]

– start all services (detached with -d). docker-compose down – stop and remove containers, networks, and volumes. docker-compose logs [-f] – view logs. docker-compose build – (re)build images. docker-compose pull – pull service images. docker-compose ps – list containers. docker-compose exec SERVICE CMD – run a command in a running container.

Compose File Basics

A typical file includes version , services , and optional networks . Example for three Ubuntu containers:

version: "3.8"
services:
  ubuntu1:
    image: ubuntu:20.04
    container_name: "ubuntu1"
    networks: [dev]
  ubuntu2:
    image: ubuntu:20.04
    container_name: "ubuntu2"
    networks: [dev, pro]
  ubuntu3:
    image: ubuntu:20.04
    container_name: "ubuntu3"
    networks: [pro]
networks:
  dev:
    driver: bridge
  pro:
    driver: bridge

Start with docker-compose up, list with docker-compose ps, and stop with docker-compose down.

Key Service Options

image – base image name (e.g., ubuntu:20.04).

build – path to a Dockerfile to build a custom image.

command – overrides the default command.

container_name – explicit container name.

restart – restart policy (e.g., always).

environment – list of environment variables.

depends_on – defines startup order.

ports – host:container port mapping (use quoted strings to avoid YAML parsing issues).

volumes – mount host paths or named volumes.

dns – custom DNS servers.

expose – expose ports internally without publishing.

links – legacy linking between services.

net – network mode (bridge, host, none).

Real‑World Example: Multiple Nginx Services

version: "3.8"
services:
  web1:
    image: nginx:1.21.4
    container_name: "web1"
    ports: ["8081:80"]
    networks: [dev]
  web2:
    image: nginx:1.21.4
    container_name: "web2"
    ports: ["8082:80"]
    networks: [dev, pro]
  web3:
    image: nginx:1.21.4
    container_name: "web3"
    ports: ["8083:80"]
    networks: [pro]
networks:
  dev:
    driver: bridge
  pro:
    driver: bridge

Start with docker-compose up -d and access the services via http://<em>host_ip</em>:8081, 8082, 8083 after opening the corresponding security‑group ports.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DevOpsContainerDockerfileDocker Compose
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.