Hướng dẫn sử dụng docker compose từ cơ bản đến nâng cao, giúp lập trình viên chỉ cần một command, có thể dễ dàng create và start toàn bộ các services phục vụ cho việc chạy ứng dụng.
Docker compose là một công cụ giúp định nghĩa và chạy multi-container cho các ứng dụng sử dụng docker. Docker compose sử dụng cú pháp YAML để định nghĩa các services, thường các service được định nghĩa trong file docker-compose.yml. Để chạy tất cả các ứng dụng được khai báo trong docker-compose.yml file chỉ cần truy cập vào thư mục chứa file docker-compose và sử dụng 1 command duy nhất docker-compose up -d 
Định nghĩa một số service để khởi chạy dự án sử dụng laravel. Các service cần thiết để chạy 1 ứng dụng sử dụng laravel: nginx(web server), app(chứa code laravel), db(database), redis, minio(môi trường giả lập s3).
Tạo file docker-compose.yml để định nghĩa các service
version: '3.4'
networks:
  backend:
    driver: bridge
services:
  nginx:
    image: nginx:1.19.2-alpine
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./docker/nginx/conf.d:/etc/nginx/conf.d
      - .:/var/www/
    links:
      - app
    depends_on:
      - app
    networks:
      - backend
  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    volumes:
      - .:/var/www/
    links:
      - db
      - redis
      - minio
    networks:
      - backend
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --skip-character-set-client-handshake
    ports:
      - "3389:3306"
    volumes:
      - mysqldata:/var/lib/mysql
      - ./docker/mysql/init/init-databases.sql:/docker-entrypoint-initdb.d/init-databases.sql
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: secret
    networks:
      - backend
  redis:
    image: redis:latest
    restart: always
    volumes:
      - ./docker/logs/redis:/var/log/redis
    ports:
      - "6379:6379"
    networks:
      - backend
    command: redis-server --appendonly yes
  minio:
    image: minio/minio
    ports:
      - "9000:9000"
    volumes:
      - ./docker/minio:/data
    tty: true
    networks:
      - backend
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
      MINIO_REGION_NAME: us-west-2
    command: ["minio", "server", "/data"]
volumes:
  mysqldata:
    driver: local
Giải thích một số chỉ thị hay dùng trong docker-compose.yml file
Version docker compose sử dụng, trong ví dụ trên mình dùng version 3.4
version: '3.4'
Khai báo network sử dụng, network này sẽ được dùng trong các container, đảm bảo các container phải dùng chung 1 network thì mới có thể truy cập được đến nhau
// Khai báo một network có tên là backend, loại network là bridge
networks:
  backend:
    driver: bridge
Khai báo các service cần dùng cho ứng dụng, mỗi một server sẽ được chạy trong 1 container
services:
  nginx:
  app:
  ...
Khai báo docker image mà service dùng để build container
// Service nginx được build từ docker image nginx:1.19.2-alpine
image: nginx:1.19.2-alpine
Chỉ định port của máy host và container
// Chỉ định port của host và container (HOST:CONTAINER)
// Truy cập vào port 81 của máy host đồng nghĩa với truy cập vào post 80 của container
ports:
      - 81:80
Mount data từ giữa container máy local, dữ liệu được link giữa máy của bạn và container, giúp không bị mất dữ liệu mỗi lân stop container
// Mount code từ thư mục cùng cấp với file docker-compose, vào trong thư mục /var/www của container
volumes:
      - .:/var/www/
Cho phép từ 1 service có thể giao tiếp với 1 hoặc nhiều service khác
app:
    // Từ service app có thể truy cập đến các service db, redis, minio
    links:
      - db
      - redis
      - minio
Định nghĩa service sử dụng network nào, các container phải dùng chung 1 network mới có thể truy cập lẫn nhau được
// Service sử dụng network backend
networks:
      - backend
Dùng để build một server từ một docker file tự viết, service app được build từ docker file trong thư mục docker/app/Dockerfile
app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
Khai báo command cần thực thi, trong container khi server được chạy
db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --skip-character-set-client-handshake
Khai báo biến môi trường cho container của db service
environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: secret
Các file dùng để thiết lập ban đầu cho các service để trong thư mục docker cùng cấp với file docker-compose.yml 
Create file docker/app/Dockerfile để build service app, chạy code laravel
FROM php:7.4-fpm AS prod
 
# Install system dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    mariadb-client \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    libonig-dev \
    locales \
    libzip-dev \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libsodium-dev \
    pkg-config
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
RUN curl -sS https://getcomposer.org/installer | \
    php -- --install-dir=/usr/local/bin --filename=composer
# Install php redis
RUN pecl install -o -f redis \
&&  rm -rf /tmp/pear \
&&  docker-php-ext-enable redis
# Set new UID for user www-data
RUN usermod -u 1000 www-data
# Set working directory
WORKDIR /var/www
COPY . .
Create file docker/nginx/conf.d/default.conf cấu hình giữa service nginx và service app
server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/public;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_hide_header X-Powered-By;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}
Create file docker/mysql/init/init-databases.sql tạo các database khi service db được chạy
# Create databases
CREATE DATABASE IF NOT EXISTS `laravel`;
CREATE DATABASE IF NOT EXISTS `laravel_test`;
Như vậy phần định nghĩa các service đã xong, giờ chạy nó thôi nào
Để buid các service được khai báo trong docker-compose.yml, Truy cập vào thư mục chứa file docker-compose.yml sau đó chạy lệnh.
docker-compose build
docker-compose up
// Chạy ở chế độ background
docker-compose up -d
// Stop các service, không bị mất dữ liệu
docker-compose stop
// Chạy các service bị stop
docker-compose start
// Các service sẽ bị down dữ liệu sẽ bị mất, phải chạy docker-compose up để chạy lại các service
docker-compose down
// Truy cập vào service app
docker-compose exec app bash
Trên đây là toàn bộ các bước để định nghĩa khởi chạy các services với docker-compose hi vọng giúp ích cho mọi người