GitHub Actions CI
ทำไมต้อง automate การ build image ใน CI?
หัวข้อที่มีชื่อว่า “ทำไมต้อง automate การ build image ใน CI?”การ build และ push image ด้วยมือเป็นสิ่งที่ผิดพลาดได้ง่าย CI pipeline ช่วยให้ทุก merge ไปยัง main branch สร้าง image ที่ผ่านการทดสอบ, มี tag, และเผยแพร่แล้ว — โดยไม่ต้องทำขั้นตอนด้วยมือ
GitHub Actions เป็นตัวเลือกที่นิยมที่สุดสำหรับโปรเจกต์บน GitHub ทีม Docker เผยแพร่ action อย่างเป็นทางการสี่ตัวที่ทำให้เรื่องนี้ง่ายขึ้นมาก:
| Action | จุดประสงค์ |
|---|---|
docker/login-action | Authenticate กับ registry ใด ๆ |
docker/setup-buildx-action | เปิดใช้ BuildKit (multi-platform, cache mounts) |
docker/metadata-action | สร้าง tag และ label จาก Git metadata |
docker/build-push-action | Build และ push ในขั้นตอนเดียว |
การตั้งค่า secrets
หัวข้อที่มีชื่อว่า “การตั้งค่า secrets”Credentials ของ registry ต้องไม่ปรากฏใน repository เด็ดขาด เก็บไว้เป็น encrypted repository secrets:
- ไปที่ repository → Settings → Secrets and variables → Actions → New repository secret
- เพิ่ม
DOCKERHUB_USERNAMEและDOCKERHUB_TOKEN(ใช้ Docker Hub access token ไม่ใช่รหัสผ่าน)
Workflow ด้านล่างอ้างอิงค่าเหล่านี้ผ่าน ${{ secrets.DOCKERHUB_USERNAME }} และ ${{ secrets.DOCKERHUB_TOKEN }} — GitHub Actions จะแทนที่ค่าจริงตอน runtime และซ่อนไว้ใน log
Workflow file
หัวข้อที่มีชื่อว่า “Workflow file”สร้าง .github/workflows/docker.yml ใน repository ของคุณ:
name: Build and push Docker image
on: push: branches: ["main"] pull_request: branches: ["main"]
jobs: build: runs-on: ubuntu-latest permissions: contents: read packages: write # needed if pushing to GHCR
steps: - name: Checkout uses: actions/checkout@v4
- name: Set up Docker Buildx uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) id: meta uses: docker/metadata-action@v5 with: images: acme/api-server tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix=sha-,format=short
- name: Build and push uses: docker/build-push-action@v6 with: context: . push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=maxการ push ไปยัง GHCR แทน Docker Hub
หัวข้อที่มีชื่อว่า “การ push ไปยัง GHCR แทน Docker Hub”หากต้องการ push ไป GitHub Container Registry ให้เปลี่ยน login step และชื่อ image:
- name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }}และอัปเดตค่า images: ใน metadata-action:
images: ghcr.io/${{ github.repository }}GITHUB_TOKEN ถูกเตรียมโดย GitHub Actions โดยอัตโนมัติ — ไม่ต้องสร้าง secret ด้วยมือ
สิ่งที่ metadata-action สร้างออกมา
หัวข้อที่มีชื่อว่า “สิ่งที่ metadata-action สร้างออกมา”สำหรับ git tag v2.1.0 metadata action จะสร้าง:
acme/api-server:2.1.0acme/api-server:2.1acme/api-server:latestacme/api-server:sha-abc1234เมื่อ push บน branch ธรรมดา (ไม่มี semver tag) จะมีเฉพาะ sha- tag และชื่อ branch — latest จะถูกตั้งค่าเฉพาะเมื่อมี tagged release เท่านั้น
BuildKit cache
หัวข้อที่มีชื่อว่า “BuildKit cache”บรรทัด cache-from: type=gha และ cache-to: type=gha,mode=max ใช้ GitHub Actions cache เก็บ BuildKit layer ระหว่าง run ซึ่งสามารถลดเวลา build ได้ 70-90% สำหรับ layer ที่ไม่เปลี่ยนแปลง
ประเด็นสำคัญ
หัวข้อที่มีชื่อว่า “ประเด็นสำคัญ”push: ${{ github.event_name != 'pull_request' }}— build ทุก PR เพื่อตรวจสอบ แต่ push เฉพาะเมื่อ merge เข้า mainsetup-buildx-actionเปิดใช้ BuildKit (layer cache, multi-platform,--mountในRUN)- ห้ามใส่ credentials ตรง ๆ ใน YAML file ใช้
secrets.*เสมอ
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
Push ไป Docker Hub ด้วย login-action | Ecosystem ใหญ่ pull ได้จากทุกที่ | ต้องสร้างและหมุนเวียน DOCKERHUB_TOKEN เอง และผูกกับ rate limit ของ Docker Hub |
Push ไป GHCR ด้วย GITHUB_TOKEN | ไม่ต้องสร้าง secret เพิ่ม permission ผูกกับ repository โดยอัตโนมัติ | Token มีอายุแค่ในระหว่าง job ใช้ pull นอก workflow ไม่ได้ตรง ๆ และผูกกับ GitHub เป็นหลัก |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- Hardcode credentials ไว้ตรง ๆ ใน workflow YAML แทนที่จะอ้างอิงผ่าน
secrets.* - ใช้รหัสผ่านธรรมดาแทน access token ใน
docker/login-action - ไม่จำกัด
permissions:ของ job ทำให้GITHUB_TOKENมีสิทธิ์กว้างเกินความจำเป็น - ฝัง credentials ไว้ใน Dockerfile layer (เช่น ผ่าน
ARGที่มี token) แทนที่จะใช้ BuildKit build secrets
💡 ตัวอย่างจากของจริง
docker/build-push-actionเป็น GitHub Action มาตรฐานที่ทีมทั่ววงการใช้ build และ push image ใน CI แทบทุก workflow ที่เกี่ยวกับ Docker บน GitHub Actions จะพึ่งพา action ตัวนี้ร่วมกับsetup-buildx-actionและmetadata-action