19. Jobs and Docker
Job in container
ปกติแล้วเราใช้ runs-on: ubuntu-latest
เป็น OS หลักในการรัน workflow ของเราใช่มะ
ถ้าเราใช้ Bun สร้าง app เราก็จะต้องติดตั้ง Bun ลงไปบน Ubuntu ก่อน แล้วค่อยสั่ง lint, test หรือ build ด้วย bun
ใช่มะ
เราสามารถใช้ Docker image ที่มี Bun ติดตั้งไว้แล้ว แทนการติดตั้ง Bun ลงไปบน Ubuntu ตรงๆ ได้เช่นกัน
อีกตัวอย่างหนึ่งคือ ถ้าเราต้องการ test React ด้วย Playwright เราก็ต้องติดตั้ง Playwright ลงไปบน Ubuntu ก่อน แล้วเราจึงจะ test ได้ ซึ่งมันก็ไม่สะดวกนัก
เราก็สามารถแก้ปัญหาได้ด้วยการที่เอา Docker image ที่มี Playwright ติดตั้งไว้แล้ว มาใช้ใน Job ที่ต้องใช้ Playwright ในการ Test
Docker image ที่จะใช้ได้ก็ทุกตัวใน Dockerhub หรือที่ registry อื่นๆก็จะใช้ได้หมดแหละ
เราจะระบุว่า Job ไหนที่จะทำงานใน Container ก็จะเขียนแบบนี้
workflows/deploy-docker.yaml
name: Deploy Projecton: push:
jobs: build: runs-on: ubuntu-latest container: image: oven/bun:1 env: NODE_ENV: production
steps: - name: Get Code uses: actions/checkout@v4
# - name: Install Bun # uses: oven-sh/setup-bun@v2 # with: # bun-version: 1.2.18
- name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
- name: Install Dependencies run: bun i
- name: Build run: bun run build
- name: upload dist folder uses: actions/upload-artifact@v4 with: name: dist path: | dist public
deploy: needs: build runs-on: ubuntu-latest steps: - name: download dist folder uses: actions/download-artifact@v4 with: name: dist
- name: List all files run: ls -R
- name: Deploy run: | echo "Deploying version ${{ needs.build.outputs.package-version }}..." echo "Commit: ${{ needs.build.outputs.build-hash }}"
ลอง push code ดู
Job build
ก็ยังทำงานได้เหมือนเดิม
พอ job build
เริ่มทำงาน มันก็จะไปโหลด docker image มารัน
แล้วทุกๆ steps ใน job ก็จะทำงานภายใน Container ที่อยู่ภายใน Ubuntu อีกที

Service Containers
ใน Github actions เราสามารถสร้าง Services ทิ้งไว้ แล้วให้ Jobs มาเรียกใช้งาน Services ได้ด้วย เช่น
เราสร้าง Database ไว้ แล้วให้ Job ทดลองเชื่อมต่อแล้ว Test ต่อไปได้
โดย Github actions ก็จะ run services ผ่าน Docker นี่แหละ จริงๆมันก็ใช้ Concept เดียวกันกับตอนที่เรา Dev บน local เลย
การเชื่อมต่อเพื่อเข้าถึง Services ก็เหมือนกันกับตอนที่เราใช้ Docker เลย
เราจะเขียน Workflow แบบนี้
ตัวอย่าง workflow
name: Services exampleon: workflow_dispatch:jobs: context: runs-on: ubuntu-latest services: redis: image: redis env: THIS_ENV: example_env ports: - 6379:6379 # surrealdb: # image: surrealdb/surrealdb env: PORT: 3000 REDIST_HOST: localhost REDIST_PORT: 6379 steps: - name: Get Code uses: actions/checkout@v4 - name: test run: bun run test
จากตัวอย่างด้านบนเราให้ Github actions สร้าง Service Redis ขึ้นมา ซึ่ง Github actions ก็จะไปสร้าง Redis ด้วย Docker แล้ว expose ออกมา ผ่าน Port 6379 แล้ว expose ออกมา ผ่าน Port 6379 และ expose ออกมา ผ่าน Port 6379
แล้วเราก็ set env REDIS_HOST: localhost
ที่ใช้ localhost
เพราะว่า steps ของเราทำงานบน Ubuntu ตรงๆ จะเห็นว่าเราไม่ได้ใช้ container:
ถ้าเราใช้ Container ก็จะเขียนแบบนี้
name: Services exampleon: workflow_dispatch:jobs: context: runs-on: ubuntu-latest container: image: oven/bun:1
services: redis: image: redis env: THIS_ENV: example_env ports: - 6379:6379 # surrealdb: # image: surrealdb/surrealdb env: PORT: 3000 REDIST_HOST: redis # REDIST_HOST: localhost REDIST_PORT: 6379 steps: - name: Get Code uses: actions/checkout@v4 - name: test run: bun run test
เมื่อเราเพิ่ม container:
เข้าไป จะทำให้ Steps ของเราทำงานใน Container ละ
พอเราอยากเข้าถึง Redis เราก็จะต้องใช้ชื่อ Service redis
แทนที่จะเป็น localhost