前言
本來是公司 server 準備改用 Docker 佈版,但因專案時程問題而延宕,最後決定在此記下部分研究成果
如果 PHP 版本為 8.2 以上,可以考慮使用 FrankenPHP。本篇因為公司專案版本較舊,使用 PHP 7.3、Laravel 8 示例
打包為 Docker image
Docker base 的選擇,因為 alpine 缺乏一些網路套件如 net-tools、iproute4,並且有 musl libc 的問題(跟 C 有關),最重要的是公司 server OS 使用 Debian。最後選擇了 bullseye
Dockerfile
1FROM php:7.3-fpm-bullseye
2
3ARG DEBIAN_FRONTEND=noninteractive
4
5# ---------- system packages ----------
6RUN apt-get update && apt-get install -y --no-install-recommends \
7 nginx \
8 supervisor \
9 git \
10 curl \
11 unzip \
12 zip \
13 libpng-dev \
14 libjpeg-dev \
15 libfreetype6-dev \
16 libzip-dev \
17 libonig-dev \
18 libxml2-dev \
19 vim \
20 libpq-dev \
21 && rm -rf /var/lib/apt/lists/*
22
23# ---------- php extensions ----------
24RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
25 && docker-php-ext-install -j$(nproc) \
26 pdo_pgsql \
27 mbstring \
28 tokenizer \
29 xml \
30 gd \
31 zip \
32 opcache
33
34# ---------- composer ----------
35COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
36
37# ---------- config ----------
38COPY docker/nginx.conf /etc/nginx/sites-available/default
39COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
40
41# ---------- app ----------
42WORKDIR /var/www/html
43COPY . .
44
45RUN composer install \
46 --no-dev \
47 --optimize-autoloader \
48 --no-interaction || true
49
50# ---------- permissions ----------
51RUN mkdir -p storage bootstrap/cache \
52 && chown -R www-data:www-data storage bootstrap/cache \
53 && chmod -R 775 storage bootstrap/cache
54
55EXPOSE 80
56
57CMD ["/usr/bin/supervisord", "-n"]
.dockerignore
1vendor
2node_modules
3.git
4.env
5storage
6tests
docker/nginx.conf
1server {
2 listen 80;
3 server_name _;
4
5 root /var/www/html/public;
6 index index.php index.html;
7
8 access_log /var/log/nginx/access.log;
9 error_log /var/log/nginx/error.log;
10
11 location / {
12 try_files $uri $uri/ /index.php?$query_string;
13 }
14
15 location ~ \.php$ {
16 include fastcgi_params;
17 fastcgi_pass 127.0.0.1:9000;
18 fastcgi_index index.php;
19 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
20 fastcgi_param PATH_INFO $fastcgi_path_info;
21 }
22
23 location ~ /\. {
24 deny all;
25 }
26}
docker/supervisord.conf
1[supervisord]
2nodaemon=true
3
4[program:php-fpm]
5command=docker-php-entrypoint php-fpm
6priority=10
7autostart=true
8autorestart=true
9stdout_logfile=/dev/stdout
10stderr_logfile=/dev/stderr
11
12[program:nginx]
13command=nginx -g "daemon off;"
14priority=20
15autostart=true
16autorestart=true
17stdout_logfile=/dev/stdout
18stderr_logfile=/dev/stderr
最後可以在本地試試看
1docker build -t elizabethhuang/laravel8 .
2docker run --name laravel8 -p 8080:80 elizabethhuang/laravel8
利用 GitHub action 包 image 並上傳至 ECR
考慮上版時的步驟,會有很多 branch 合併、封版測試,完成後確認版號。因此這個包 image 的操作可以限制在有指定版號才動作
首先,在 ECR 建立 repo。這裡有個小坑,ap-east-2(臺北)不支援 CodePipeline,如果想用 CodePipeline 作為 CI tool 的話,需要注意一下 region
在 GitHub action secret 新增 AWS_DEPLOY_ROLE 和 AWS_DEFAULT_REGION,這些 AWS OIDC 要用。然後 variable 新增 ECR_REPOSITORY,也就是 ECR repo 名稱
.github/workflows/build.yml
1name: Build Docker image
2
3on:
4 workflow_dispatch:
5
6permissions:
7 id-token: write
8 contents: read
9
10jobs:
11 run_job_with_aws:
12 runs-on: ubuntu-24.04-arm
13 # Check whether the ref contains tag.
14 if: startsWith(github.ref, 'refs/tags/v')
15 steps:
16 - name: Set version tag env
17 run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
18
19 - name: Checkout repository
20 uses: actions/checkout@v4
21
22 - name: Configure AWS Credentials
23 uses: aws-actions/configure-aws-credentials@main
24 with:
25 role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE }}
26 aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
27
28 - name: Login to Amazon ECR
29 id: login-ecr
30 uses: aws-actions/amazon-ecr-login@v2
31
32 - name: Build and push Docker image
33 env:
34 ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
35 ECR_REPOSITORY: ${{vars.ECR_REPOSITORY }}
36 IMAGE_TAG: ${{ env.RELEASE_VERSION }}
37 run: |
38 docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
39 docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
另外,恭喜現在 Github action public repo 也能使用 arm runner 了!AWS 的 arm 機器比較便宜,但聽前輩說 AWS 相同 arm 不同 instance type 服務效率可能產生巨大差距,因此真的要服務轉移還是實測才準,在自己帳戶玩玩還是可以用 arm 省點摳摳
Next step…
image 上傳至 ECR 後,接下來就能使用 ECS 部署到 EC2 上了
我使用 Terraform 啟動整個資源,但目前工作重心轉移到功能開發上,研究進度中斷,若有空閑時間再完善整個 Terraform + GitHub action 部署