- ภาพรวม Workflow
- 1. เตรียม Docker Image
- 2. Push Docker Image ขึ้น Docker Hub
- 3. Push Docker Image ขึ้น GitHub Container Registry
- 4. Push Docker Image ขึ้น GitLab Container Registry
- 5. เปรียบเทียบชื่อ Image
- 6. การกำหนด Version ของ Docker Image
- 7. ใช้ Git Commit SHA เป็น Image Tag
- 8. นำไปใช้กับ Docker Compose
- 9. นำไปใช้กับ Kubernetes
- 10. Workflow สำหรับ CI/CD
- 11. แนวทางที่แนะนำสำหรับ Production
- สรุป
เมื่อเราสร้างระบบด้วย Docker ขั้นตอนสำคัญหลังจาก docker build คือการนำ Docker
Image ไปเก็บไว้บน Container Registry เพื่อให้ Server, Kubernetes, CI/CD
Pipeline หรือสมาชิกในทีมสามารถดาวน์โหลด Image เวอร์ชันเดียวกันไปใช้งานได้
บทความนี้อธิบายการ Push Docker Image ไปยัง Registry ที่นิยมใช้งาน 3 แห่ง ได้แก่
- Docker Hub
- GitHub Container Registry (GHCR)
- GitLab Container Registry
#ภาพรวม Workflow
Source Code
|
v
Dockerfile
|
| docker build
v
Local Docker Image
|
| tag + login + push
v
Container Registry
|
+---- Docker Hub
+---- GitHub Container Registry
+---- GitLab Container Registry
|
| docker pull
v
Development / Server / CI-CD / Kubernetes
หลักการทำงานของทั้งสามระบบใกล้เคียงกันมาก คือ
Build -> Tag -> Login -> Push -> Pull/Deploy
#1. เตรียม Docker Image
สมมติว่าเรามีโปรเจกต์ชื่อ my-app
my-app/
├── Dockerfile
├── package.json
└── src/
สร้าง Image ด้วยคำสั่ง
docker build -t my-app:1.0 .
ตรวจสอบ Image
docker images
ตัวอย่างผลลัพธ์
REPOSITORY TAG IMAGE ID CREATED SIZE
my-app 1.0 abc123456789 1 minute ago 180MB
ก่อน Push ควรทดลองรัน Image ก่อน
docker run --rm -p 8080:8080 my-app:1.0
ถ้า Application ทำงานถูกต้องจึงค่อยนำ Image ไป Push ขึ้น Registry
#2. Push Docker Image ขึ้น Docker Hub
Docker Hub เป็น Public Container Registry ที่ใช้งานแพร่หลาย และสามารถใช้งานร่วมกับ Docker CLI ได้โดยตรง
เว็บไซต์: https://hub.docker.com/
รูปแบบชื่อ Image โดยทั่วไปคือ
USERNAME/IMAGE_NAME:TAG
ตัวอย่าง
naruapon/my-app:1.0
#Login Docker Hub
docker login
Docker จะให้กรอก Username และ Password/Access Token ตามวิธี Authentication ที่บัญชีรองรับ
#Tag Image
Image ที่สร้างไว้คือ
my-app:1.0
สร้าง Tag สำหรับ Docker Hub
docker tag my-app:1.0 naruapon/my-app:1.0
ตรวจสอบ
docker images
จะพบทั้งชื่อเดิมและชื่อที่ Tag ใหม่ โดยทั้งสองอาจอ้างถึง Image ID เดียวกัน
#Push Image
docker push naruapon/my-app:1.0
จากนั้นเครื่องอื่นสามารถ Pull ได้ด้วย
docker pull naruapon/my-app:1.0
และรันด้วย
docker run --rm -p 8080:8080 naruapon/my-app:1.0
#การใช้ latest
สามารถสร้าง latest tag เพิ่มได้
docker tag my-app:1.0 naruapon/my-app:latest
docker push naruapon/my-app:latest
อย่างไรก็ตาม ใน Production ควรระบุ Version ที่แน่นอน เช่น 1.0.0 หรือ 2.1.3
แทนการอ้าง latest เพียงอย่างเดียว
#3. Push Docker Image ขึ้น GitHub Container Registry
GitHub มี Container Registry หรือ GHCR ซึ่งทำงานร่วมกับ GitHub Repository และ GitHub Actions ได้สะดวก
Registry URL คือ
ghcr.io
รูปแบบชื่อ Image
ghcr.io/OWNER/IMAGE_NAME:TAG
ตัวอย่าง
ghcr.io/naruapon/my-app:1.0
#Login GHCR
การใช้งานจากเครื่อง Local สามารถใช้ Token ที่มี Permission เหมาะสม
ตัวอย่างเก็บ Token ใน Environment Variable
export CR_PAT=YOUR_TOKEN
จากนั้น Login
echo "$CR_PAT" | docker login ghcr.io -u USERNAME --password-stdin
ไม่ควรเขียน Token ลงใน Dockerfile, Source Code หรือ Commit ลง Git Repository
#Tag Image
docker tag my-app:1.0 ghcr.io/naruapon/my-app:1.0
#Push
docker push ghcr.io/naruapon/my-app:1.0
#Pull
docker pull ghcr.io/naruapon/my-app:1.0
หาก Package เป็น Private ผู้ใช้หรือระบบที่ Pull จะต้องมีสิทธิ์ในการเข้าถึง Package นั้นด้วย
#4. Push Docker Image ขึ้น GitLab Container Registry
GitLab มี Container Registry เชื่อมโยงกับ Project และ GitLab CI/CD โดยตรง
Registry หลักของ GitLab.com คือ
registry.gitlab.com
รูปแบบชื่อ Image โดยทั่วไปคือ
registry.gitlab.com/NAMESPACE/PROJECT/IMAGE:TAG
ตัวอย่าง
registry.gitlab.com/naruapon/my-project/my-app:1.0
เอกสาร: https://docs.gitlab.com/user/packages/container_registry/
#Login
docker login registry.gitlab.com
หรือใช้ Token
echo "$TOKEN" | docker login registry.gitlab.com \
-u USERNAME \
--password-stdin
#Tag Image
docker tag my-app:1.0 \
registry.gitlab.com/naruapon/my-project/my-app:1.0
#Push
docker push \
registry.gitlab.com/naruapon/my-project/my-app:1.0
#Pull
docker pull \
registry.gitlab.com/naruapon/my-project/my-app:1.0
#5. เปรียบเทียบชื่อ Image
Registry รูปแบบ ตัวอย่าง
Docker Hub user/image:tag naruapon/my-app:1.0
GitHub GHCR ghcr.io/owner/image:tag ghcr.io/naruapon/my-app:1.0
#GitLab registry.gitlab.com/namespace/project/image:tag registry.gitlab.com/naruapon/my-project/my-app:1.0
สังเกตว่า Docker Image ตัวเดียวกันสามารถ Tag ได้หลายชื่อ
docker tag my-app:1.0 naruapon/my-app:1.0
docker tag my-app:1.0 ghcr.io/naruapon/my-app:1.0
docker tag my-app:1.0 registry.gitlab.com/naruapon/my-project/my-app:1.0
จากนั้นจึง Push ไปยังแต่ละ Registry
docker push naruapon/my-app:1.0
docker push ghcr.io/naruapon/my-app:1.0
docker push registry.gitlab.com/naruapon/my-project/my-app:1.0
#6. การกำหนด Version ของ Docker Image
ไม่ควรใช้ latest เพียง Tag เดียวในระบบ Production
ตัวอย่างที่เหมาะสมกว่า
my-app:1.0.0
my-app:1.1.0
my-app:1.2.0
my-app:2.0.0
อาจสร้างทั้ง Version และ latest
docker tag my-app:1.2.0 naruapon/my-app:1.2.0
docker tag my-app:1.2.0 naruapon/my-app:latest
docker push naruapon/my-app:1.2.0
docker push naruapon/my-app:latest
ข้อดีของ Version Tag คือสามารถระบุ Image ที่ต้อง Deploy และ Rollback ได้ชัดเจน
#7. ใช้ Git Commit SHA เป็น Image Tag
ในระบบ CI/CD สามารถใช้ Git Commit SHA เป็น Tag ได้ เช่น
my-app:a1b2c3d
ตัวอย่าง
docker build -t my-app:a1b2c3d .
docker tag my-app:a1b2c3d ghcr.io/naruapon/my-app:a1b2c3d
docker push ghcr.io/naruapon/my-app:a1b2c3d
แนวทางนี้ช่วยเชื่อมโยง Docker Image กับ Source Code ที่ใช้สร้าง Image ได้โดยตรง
Git Commit a1b2c3d
|
v
Docker Build
|
v
my-app:a1b2c3d
|
v
Container Registry
|
v
Deployment
#8. นำไปใช้กับ Docker Compose
เมื่อ Image ถูก Push ไปยัง Registry แล้ว เครื่อง Production ไม่จำเป็นต้อง Build Source Code ใหม่
ตัวอย่าง compose.yaml
services:
web:
image: ghcr.io/naruapon/my-app:1.0.0
ports:
- "8080:8080"
ดึง Image
docker compose pull
จากนั้น
docker compose up -d
#9. นำไปใช้กับ Kubernetes
Container Registry มีบทบาทสำคัญมากในการ Deploy Kubernetes
ตัวอย่าง Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: ghcr.io/naruapon/my-app:1.0.0
ports:
- containerPort: 8080
Kubernetes จะ Pull Image จาก Registry เพื่อนำไปสร้าง Container บนแต่ละ Node
GitHub / GitLab
|
v
CI/CD Pipeline
|
| docker build
v
Docker Image
|
| docker push
v
Container Registry
|
| docker pull
v
Kubernetes Cluster
|
+-- Pod
+-- Pod
+-- Pod
หาก Registry เป็น Private จะต้องตั้งค่า Credential สำหรับ Cluster อย่างเหมาะสม
#10. Workflow สำหรับ CI/CD
ในงานจริงเราไม่จำเป็นต้อง Build และ Push ด้วยมือทุกครั้ง
สามารถสร้าง Pipeline ให้ทำงานอัตโนมัติเมื่อ
git push
|
v
GitHub Actions / GitLab CI
|
+-- Checkout Source
|
+-- Login Registry
|
+-- Docker Build
|
+-- Docker Tag
|
+-- Docker Push
|
v
Container Registry
|
v
Deploy
ตัวอย่างแนวคิด GitHub Actions:
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/example/my-app:latest
ควรตรวจสอบเวอร์ชันของ GitHub Actions ที่ใช้งานจากเอกสารทางการก่อนนำ Pipeline ไปใช้จริง
#11. แนวทางที่แนะนำสำหรับ Production
ควรปฏิบัติตามแนวทางต่อไปนี้
- ไม่เก็บ Password หรือ Access Token ไว้ใน Source Code
- ใช้ CI/CD Secrets สำหรับ Credential
- ใช้ Version Tag หรือ Commit SHA เพื่อระบุ Image
- หลีกเลี่ยงการพึ่ง
latestเพียงอย่างเดียว - Scan Image เพื่อค้นหา Vulnerability
- ใช้ Multi-stage Build เพื่อลดขนาด Image
- ใช้
.dockerignoreเพื่อลด Build Context - กำหนดสิทธิ์ Registry และ Token ตามหลัก Least Privilege
- อย่า Push
.env, Private Key หรือ Secret เข้าไปใน Image - สำหรับ Production ที่ต้องการความแน่นอนสูง อาจ Deploy ด้วย Image Digest เช่น
image@sha256:...
#สรุป
ไม่ว่าจะใช้ Docker Hub, GitHub Container Registry หรือ GitLab Container Registry หลักการสำคัญเหมือนกันคือ
docker build
|
v
docker tag
|
v
docker login
|
v
docker push
|
v
Container Registry
|
v
docker pull
|
v
Deploy
Docker Hub เหมาะกับการเผยแพร่และแชร์ Docker Image โดยทั่วไป ขณะที่ GHCR เหมาะกับ Workflow ที่ใช้ GitHub และ GitHub Actions ส่วน GitLab Container Registry เหมาะกับโครงการที่ใช้ GitLab และ GitLab CI/CD
เมื่อพัฒนาต่อไปสู่ระบบ Production ควรให้ CI/CD Pipeline เป็นผู้ Build, Tag และ Push Image โดยอัตโนมัติ และให้ Docker Compose, Kubernetes, Helm หรือ GitOps ดึง Image ที่ระบุ Version ชัดเจนไป Deploy
#เอกสารอ้างอิง
- Docker Hub: https://hub.docker.com/
- GitHub Container Registry: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry
- GitLab Container Registry: https://docs.gitlab.com/user/packages/container_registry/