{"id":24,"date":"2026-09-07T11:54:34","date_gmt":"2026-09-07T11:54:34","guid":{"rendered":"http:\/\/127.0.0.1:8080\/index.php\/2026\/09\/07\/tu-dong-hoa-trien-khai-ci-cd-voi-github-actions-va-docker-container\/"},"modified":"2026-09-07T11:54:34","modified_gmt":"2026-09-07T11:54:34","slug":"tu-dong-hoa-trien-khai-ci-cd-voi-github-actions-va-docker-container","status":"publish","type":"post","link":"https:\/\/zunliz.com\/index.php\/2026\/09\/07\/tu-dong-hoa-trien-khai-ci-cd-voi-github-actions-va-docker-container\/","title":{"rendered":"T\u1ef1 \u0110\u1ed9ng H\u00f3a Tri\u1ec3n Khai CI\/CD v\u1edbi GitHub Actions v\u00e0 Docker Container"},"content":{"rendered":"<p>Quy tr\u00ecnh T\u00edch h\u1ee3p Li\u00ean t\u1ee5c v\u00e0 Tri\u1ec3n khai Li\u00ean t\u1ee5c (Continuous Integration \/ Continuous Deployment &#8211; CI\/CD) l\u00e0 x\u01b0\u01a1ng s\u1ed1ng c\u1ee7a m\u1ecdi \u0111\u1ed9i ng\u0169 ph\u00e1t tri\u1ec3n ph\u1ea7n m\u1ec1m Agile. Vi\u1ec7c t\u1ef1 \u0111\u1ed9ng h\u00f3a to\u00e0n b\u1ed9 qu\u00e1 tr\u00ecnh ki\u1ec3m th\u1eed, \u0111\u00f3ng g\u00f3i Docker Image v\u00e0 deploy l\u00ean m\u00e1y ch\u1ee7 gi\u00fap lo\u1ea1i b\u1ecf 99% l\u1ed7i do thao t\u00e1c th\u1ee7 c\u00f4ng.<\/p>\n\n\n<h2 class=\"wp-block-heading\">1. C\u1ea5u tr\u00fac m\u1ed9t Pipeline CI\/CD Ti\u00eau chu\u1ea9n<\/h2>\n\n<ol>\n  <li><strong>Lint &amp; Type Check:<\/strong> Ki\u1ec3m tra \u0111\u1ecbnh d\u1ea1ng code v\u00e0 ki\u1ec3m tra ki\u1ec3u d\u1eef li\u1ec7u t\u0129nh.<\/li>\n  <li><strong>Unit &amp; Integration Test:<\/strong> T\u1ef1 \u0111\u1ed9ng ch\u1ea1y to\u00e0n b\u1ed9 b\u00e0i ki\u1ec3m th\u1eed t\u1ef1 \u0111\u1ed9ng, \u0111\u1ea3m b\u1ea3o t\u00ednh n\u0103ng m\u1edbi kh\u00f4ng l\u00e0m h\u1ecfng logic c\u0169.<\/li>\n  <li><strong>Docker Build &amp; Push:<\/strong> \u0110\u00f3ng g\u00f3i \u1ee9ng d\u1ee5ng th\u00e0nh Docker Image v\u00e0 \u0111\u1ea9y l\u00ean Docker Hub ho\u1eb7c GitHub Container Registry (GHCR).<\/li>\n  <li><strong>Deploy (SSH\/Webhook):<\/strong> K\u00edch ho\u1ea1t m\u00e1y ch\u1ee7 production t\u1ea3i image m\u1edbi v\u00e0 restart container kh\u00f4ng gi\u00e1n \u0111o\u1ea1n (Zero-Downtime Deployment).<\/li>\n<\/ol>\n\n\n<h2 class=\"wp-block-heading\">2. File C\u1ea5u h\u00ecnh GitHub Actions Workflow Ho\u00e0n ch\u1ec9nh<\/h2>\n\n<p>T\u1ea1o file <code>.github\/workflows\/deploy.yml<\/code> trong repository:<\/p>\n\n<pre><code class=\"language-yaml\">name: Production CI\/CD Pipeline\n\non:\n  push:\n    branches: [ \"main\" ]\n\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Source Code\n        uses: actions\/checkout@v4\n\n      - name: Set up Docker Buildx\n        uses: docker\/setup-buildx-action@v3\n\n      - name: Log in to GitHub Container Registry\n        uses: docker\/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Build and Push Docker Image\n        uses: docker\/build-push-action@v5\n        with:\n          context: .\n          push: true\n          tags: ghcr.io\/${{ github.repository }}:latest\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n\n      - name: Deploy to Remote Server via SSH\n        uses: appleboy\/ssh-action@v1.0.3\n        with:\n          host: ${{ secrets.SERVER_HOST }}\n          username: ${{ secrets.SERVER_USER }}\n          key: ${{ secrets.SERVER_SSH_KEY }}\n          script: |\n            docker pull ghcr.io\/${{ github.repository }}:latest\n            docker compose down\n            docker compose up -d --remove-orphans<\/code><\/pre>\n\n\n<h2 class=\"wp-block-heading\">3. Qu\u1ea3n l\u00fd Secrets v\u00e0 B\u1ea3o m\u1eadt Pipeline<\/h2>\n\n<p>Tuy\u1ec7t \u0111\u1ed1i kh\u00f4ng l\u01b0u m\u1eadt kh\u1ea9u, SSH key hay API token tr\u1ef1c ti\u1ebfp trong git. Lu\u00f4n s\u1eed d\u1ee5ng <strong>GitHub Encrypted Secrets<\/strong> v\u00e0 c\u1ea5p quy\u1ec1n t\u1ed1i thi\u1ec3u (Least Privilege) cho c\u00e1c Service Account k\u1ebft n\u1ed1i v\u00e0o h\u1ec7 th\u1ed1ng.<\/p>","protected":false},"excerpt":{"rendered":"<p>Quy tr\u00ecnh T\u00edch h\u1ee3p Li\u00ean t\u1ee5c v\u00e0 Tri\u1ec3n khai Li\u00ean t\u1ee5c (Continuous Integration \/ Continuous Deployment &#8211; CI\/CD) l\u00e0 x\u01b0\u01a1ng s\u1ed1ng c\u1ee7a m\u1ecdi \u0111\u1ed9i ng\u0169 ph\u00e1t tri\u1ec3n ph\u1ea7n m\u1ec1m Agile. Vi\u1ec7c t\u1ef1 \u0111\u1ed9ng h\u00f3a to\u00e0n b\u1ed9 qu\u00e1 tr\u00ecnh ki\u1ec3m th\u1eed, \u0111\u00f3ng g\u00f3i Docker Image v\u00e0 deploy l\u00ean m\u00e1y ch\u1ee7 gi\u00fap lo\u1ea1i b\u1ecf 99% l\u1ed7i do [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,3],"tags":[],"class_list":["post-24","post","type-post","status-publish","format-standard","hentry","category-bao-mat-devops","category-cong-nghe-lap-trinh"],"_links":{"self":[{"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/posts\/24","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/comments?post=24"}],"version-history":[{"count":0,"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/posts\/24\/revisions"}],"wp:attachment":[{"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/media?parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/categories?post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zunliz.com\/index.php\/wp-json\/wp\/v2\/tags?post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}