📦 Docker

容器化應用部署的業界標準

Docker 讓應用與其相依環境打包成映像檔,實現「一次建置,到處執行」,是現代 CI/CD 與 DevOps 的核心工具,大幅減少「在我機器上可以跑」的問題。

安裝 Docker Engine

使用官方腳本一鍵安裝(Ubuntu/Debian):

$ curl -fsSL https://get.docker.com | sudo sh
$ # 將目前使用者加入 docker 群組(免 sudo)
sudo usermod -aG docker $USER
newgrp docker    # 或重新登入
$ docker version
Client: Docker Engine - Community
 Version:           26.1.3

核心概念

名詞說明
映像檔(Image)唯讀的應用程式模板,從 Dockerfile 建置或從 Registry 下載
容器(Container)映像檔的執行實例,可讀寫,停止後資料消失(需掛載 Volume)
Registry儲存映像檔的倉庫,公開倉庫為 Docker Hub
Volume資料持久化掛載點,容器刪除後資料保留
Network容器間的虛擬網路,同網路的容器可用服務名稱互相連線

映像檔管理

$ docker pull nginx:1.26-alpine      # 下載映像檔
$ docker images                       # 列出本機映像檔
$ docker rmi nginx:1.26-alpine        # 刪除映像檔
$ docker image prune                  # 清除無用的懸掛映像檔

撰寫 Dockerfile

# 以 Node.js 應用為例
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
$ docker build -t myapp:1.0 .         # 建置映像檔

容器操作

操作指令
啟動容器(前景)docker run -it ubuntu bash
啟動容器(背景)docker run -d -p 80:80 nginx
列出執行中的容器docker ps
列出所有容器(含停止)docker ps -a
進入容器 Shelldocker exec -it 容器名 bash
查看日誌docker logs -f 容器名
停止容器docker stop 容器名
刪除容器docker rm 容器名
清除所有停止的容器docker container prune

網路設定

$ # 建立自訂網路
docker network create mynet

# 在同一網路啟動兩個容器,可用服務名互連
docker run -d --name db --network mynet mysql:8
docker run -d --name app --network mynet -e DB_HOST=db myapp:1.0
$ docker network ls                   # 列出所有網路

資料持久化(Volume)

$ # 具名 Volume(推薦,由 Docker 管理)
docker run -d \
  -v mysql-data:/var/lib/mysql \
  --name db mysql:8

# Bind Mount(直接對應主機目錄)
docker run -d \
  -v /home/user/html:/usr/share/nginx/html:ro \
  -p 80:80 nginx
$ docker volume ls                    # 列出所有 Volume
docker volume prune                 # 清除無容器使用的 Volume

實用技巧

$ # 一次清理所有無用資源(映像檔、容器、網路、Volume)
docker system prune -a --volumes
$ # 查看容器資源使用狀況(CPU/記憶體)
docker stats
$ # 複製檔案(主機 ↔ 容器)
docker cp ./config.yml myapp:/app/config.yml
docker cp myapp:/app/logs ./local-logs/
⚠️ 容器本身是無狀態的,應用的持久化資料(資料庫、上傳檔案)必須掛載 Volume,否則容器刪除後資料將消失。