Deploy แอปพลิเคชัน PHP ด้วย Docker
มาถึงบทสุดท้ายของซีรีส์ Docker สำหรับนักพัฒนา PHP แล้วครับ! หลังจากที่เราได้เรียนรู้พื้นฐานการใช้งาน Docker ตั้งแต่การสร้าง Dockerfile ไปจนถึงการจัดการ Container และ Best Practices ต่างๆ ในการพัฒนา วันนี้เราจะมาเรียนรู้วิธีการนำแอปพลิเคชัน PHP ที่เราสร้างขึ้นด้วย Docker ไปใช้งานจริง (Deploy) บน Production Environment กันครับ
การ Deploy แอปพลิเคชันด้วย Docker ช่วยให้เรามั่นใจได้ว่าแอปพลิเคชันของเราจะทำงานได้เหมือนกันทุกสภาพแวดล้อม ไม่ว่าจะเป็น Local Development, Staging หรือ Production เนื่องจากเราได้สร้าง Image ที่มีทุกอย่างที่แอปพลิเคชันต้องการไว้แล้ว (Dependencies, Configuration, Code) ทำให้ลดปัญหา "It works on my machine!" ที่เรามักเจอกันบ่อยๆ ครับ
Docker Hub และ Docker Registry
ก่อนที่เราจะไปถึงขั้นตอนการ Deploy เราต้องทำความเข้าใจก่อนว่า Docker Image ที่เราสร้างขึ้นมานั้น เราจะเก็บไว้ที่ไหน? คำตอบคือเราจะเก็บไว้ใน Docker Registry ครับ
Docker Registry คือที่เก็บ Image ของ Docker ซึ่งมีทั้งแบบ Public และ Private ครับ
- Docker Hub: คือ Docker Registry สาธารณะที่ใหญ่ที่สุดและใช้งานกันอย่างแพร่หลาย เราสามารถ Push (อัปโหลด) Image ของเราขึ้นไปไว้บน Docker Hub ได้ฟรี (มีข้อจำกัดเรื่อง Private Repository) Docker Hub เป็นที่ที่เราสามารถค้นหา Image สำเร็จรูปที่คนอื่นสร้างไว้ได้มากมาย เช่น Image ของ PHP, MySQL, Nginx เป็นต้น
- Private Docker Registry: หากเราต้องการเก็บ Image ของเราไว้เป็นส่วนตัว (เช่น Image ที่มี Source Code ที่เราไม่อยากเปิดเผย) เราสามารถสร้าง Private Docker Registry ขึ้นมาใช้งานเองได้ หรือใช้บริการ Private Registry ที่มีผู้ให้บริการหลายราย เช่น Amazon ECR, Google Container Registry, Azure Container Registry
Trade-off: การใช้ Docker Hub สะดวกและง่าย แต่ Image จะเป็น Public โดย default (ต้องเสียเงินสำหรับ Private Repository) ส่วน Private Docker Registry จะมีความปลอดภัยมากกว่า แต่ต้องดูแลรักษาเอง
ในบทความนี้ เราจะใช้ Docker Hub เป็นตัวอย่างในการ Deploy แอปพลิเคชัน PHP ของเราครับ
ขั้นตอนการใช้งาน Docker Hub
- สร้าง Account บน Docker Hub: เข้าไปที่ https://hub.docker.com/ และสร้าง Account ให้เรียบร้อย
- Login เข้าสู่ Docker Hub บนเครื่องของคุณ: เปิด Terminal แล้วพิมพ์คำสั่ง
docker loginจากนั้นกรอก Username และ Password ที่คุณใช้สมัคร Docker Hub - Tag Image ของคุณ: ก่อนที่จะ Push Image ขึ้นไปบน Docker Hub เราต้อง Tag Image ของเราให้มีรูปแบบ
username/repository:tagโดยที่usernameคือ Username ของคุณบน Docker Hub,repositoryคือชื่อ Repository ที่คุณต้องการสร้าง (เช่นmy-php-app) และtagคือ Version ของ Image (เช่นlatest,1.0)docker tag my-php-app:latest your_dockerhub_username/my-php-app:latest - Push Image ขึ้นไปบน Docker Hub: ใช้คำสั่ง
docker pushเพื่อ Push Image ขึ้นไปบน Docker Hubdocker push your_dockerhub_username/my-php-app:latest
docker login
หลังจาก Push Image สำเร็จแล้ว คุณจะสามารถเข้าไปดู Image ของคุณได้บน Docker Hub ครับ
CI/CD Pipelines
เมื่อเรามี Image อยู่บน Docker Registry แล้ว ขั้นตอนต่อไปคือการ Deploy แอปพลิเคชัน PHP ของเราไปยัง Production Environment ครับ แต่การ Deploy ด้วยมือทุกครั้งที่มีการเปลี่ยนแปลง Code นั้นไม่ใช่เรื่องสนุกและอาจเกิดข้อผิดพลาดได้ง่าย ดังนั้นเราจึงควรใช้ CI/CD Pipelines (Continuous Integration/Continuous Delivery or Continuous Deployment) เพื่อ Automate ขั้นตอนการ Deploy ครับ
CI/CD Pipelines คือชุดของขั้นตอนที่ Automate กระบวนการ Build, Test และ Deploy แอปพลิเคชันของเรา โดยมีเครื่องมือมากมายที่เราสามารถนำมาใช้สร้าง CI/CD Pipelines ได้ เช่น
- Jenkins: Open Source Automation Server ที่ได้รับความนิยม สามารถปรับแต่งได้หลากหลาย
- GitLab CI/CD: CI/CD ที่ Built-in อยู่ใน GitLab
- GitHub Actions: CI/CD ที่ Built-in อยู่ใน GitHub
- CircleCI: Cloud-Based CI/CD Platform
- Travis CI: Cloud-Based CI/CD Platform
Trade-off: Jenkins มีความยืดหยุ่นสูง แต่ต้องดูแลรักษาเอง ส่วน Cloud-Based CI/CD Platform จะใช้งานง่ายกว่า แต่มีค่าใช้จ่าย
ในบทความนี้ เราจะยกตัวอย่างการใช้ GitHub Actions ในการสร้าง CI/CD Pipeline ง่ายๆ สำหรับ Deploy แอปพลิเคชัน PHP ของเราครับ
ตัวอย่าง GitHub Actions Workflow
สมมติว่าเรามี Repository บน GitHub ที่มี Source Code ของแอปพลิเคชัน PHP ของเรา และมี Dockerfile ที่เราได้สร้างไว้แล้ว เราสามารถสร้าง Workflow ใน GitHub Actions เพื่อ Automate ขั้นตอนการ Build Docker Image, Push Image ขึ้น Docker Hub และ Deploy แอปพลิเคชันไปยัง Server ของเราได้ดังนี้
- สร้าง Directory
.github/workflowsใน Repository ของคุณ: Directory นี้จะเป็นที่เก็บ Workflow Files ของ GitHub Actions - สร้าง File
deploy.ymlใน Directory.github/workflows: File นี้จะเป็น Workflow Definition File ที่เราจะกำหนดขั้นตอนการทำงานของ CI/CD Pipeline - ใส่ Code ต่อไปนี้ใน File
deploy.yml:name: Deploy PHP App on: push: branches: [ "main" ] # Trigger เมื่อมีการ Push Code ไปยัง Branch "main" jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 # Checkout Code จาก Repository - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} # อ่านค่า Username จาก GitHub Secrets password: ${{ secrets.DOCKERHUB_TOKEN }} # อ่านค่า Token จาก GitHub Secrets - name: Build and Push Docker Image uses: docker/build-push-action@v4 with: context: . # Build จาก Directory ปัจจุบัน push: true # Push Image ขึ้น Docker Hub tags: your_dockerhub_username/my-php-app:${{ github.sha }} # Tag Image ด้วย Commit SHA latest: your_dockerhub_username/my-php-app:latest # Tag Image ด้วย latest - name: SSH into Server and Pull Latest Image uses: appleboy/ssh-action@v0.1.10 with: host: ${{ secrets.SERVER_IP }} # อ่านค่า IP Address ของ Server จาก GitHub Secrets username: ${{ secrets.SERVER_USERNAME }} # อ่านค่า Username ของ Server จาก GitHub Secrets key: ${{ secrets.SERVER_PRIVATE_KEY }} # อ่านค่า Private Key ของ Server จาก GitHub Secrets script: | docker pull your_dockerhub_username/my-php-app:latest docker stop my-php-app || true # Stop Container หากมีอยู่ docker rm my-php-app || true # Remove Container หากมีอยู่ docker run -d -p 80:80 --name my-php-app your_dockerhub_username/my-php-app:latest # Run Container - กำหนด Secrets ใน GitHub Repository: ใน Workflow File เราได้ใช้ Secrets หลายตัว เช่น
DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,SERVER_IP,SERVER_USERNAME,SERVER_PRIVATE_KEYเราต้องกำหนดค่าเหล่านี้ใน GitHub Repository Settings -> Secrets -> Actions เพื่อให้ GitHub Actions สามารถเข้าถึงค่าเหล่านี้ได้อย่างปลอดภัยDOCKERHUB_USERNAME: Username ของคุณบน Docker HubDOCKERHUB_TOKEN: Docker Hub Access Token (สร้างได้จาก Docker Hub Settings)SERVER_IP: IP Address ของ Server ที่เราจะ Deploy แอปพลิเคชันSERVER_USERNAME: Username สำหรับ SSH เข้า ServerSERVER_PRIVATE_KEY: Private Key สำหรับ SSH เข้า Server (ควรใช้ Deploy Key ที่มีสิทธิ์จำกัด)
คำอธิบาย Workflow:
- Workflow นี้จะ Trigger เมื่อมีการ Push Code ไปยัง Branch
main - Workflow จะ Login เข้าสู่ Docker Hub ด้วย Username และ Token ที่เรากำหนดไว้ใน GitHub Secrets
- Workflow จะ Build Docker Image จาก Dockerfile ใน Repository และ Push Image ขึ้น Docker Hub โดย Tag Image ด้วย Commit SHA และ
latest - Workflow จะ SSH เข้าไปยัง Server ของเรา และ Pull Docker Image ล่าสุดจาก Docker Hub
- Workflow จะ Stop และ Remove Container เดิม (ถ้ามี) และ Run Container ใหม่ด้วย Image ล่าสุด
เมื่อเรา Push Code ไปยัง Branch main ของ Repository Workflow นี้จะทำงานโดยอัตโนมัติ และ Deploy แอปพลิเคชัน PHP ของเราไปยัง Server ของเราครับ
ข้อควรระวัง: ตัวอย่างนี้เป็นเพียง Workflow ง่ายๆ สำหรับ Deploy แอปพลิเคชัน PHP ไปยัง Server เดียว ใน Production Environment จริง เราอาจต้องใช้เครื่องมือและเทคนิคที่ซับซ้อนกว่านี้ เช่น Load Balancing, Auto Scaling, Zero-Downtime Deployment เป็นต้น
สรุป
ในบทนี้ เราได้เรียนรู้วิธีการ Deploy แอปพลิเคชัน PHP ด้วย Docker ไปยัง Production Environment โดยใช้ Docker Hub เป็น Docker Registry และ GitHub Actions เป็น CI/CD Pipeline เราได้เห็นว่าการใช้ Docker ช่วยให้เรา Automate ขั้นตอนการ Deploy และทำให้แอปพลิเคชันของเราทำงานได้อย่างราบรื่นในทุกสภาพแวดล้อม
หวังว่าซีรีส์ Docker สำหรับนักพัฒนา PHP นี้จะเป็นประโยชน์กับทุกท่านนะครับ ขอให้สนุกกับการพัฒนาแอปพลิเคชัน PHP ด้วย Docker ครับ!