• 实战多阶段构建 Laravel 镜像
    • 准备
    • 前端构建
    • 安装 Composer 依赖
    • 整合以上阶段所生成的文件
    • 最后一个阶段构建 NGINX 镜像
    • 构建 Laravel 及 Nginx 镜像
    • 启动容器并测试
    • 生产环境优化
    • 附录

    实战多阶段构建 Laravel 镜像

    本节适用于 PHP 开发者阅读。

    准备

    新建一个 Laravel 项目或在已有的 Laravel 项目根目录下新建 Dockerfile .dockerignore laravel.conf 文件。

    .dockerignore 文件中写入以下内容。

    1. .idea/
    2. .git/
    3. vendor/
    4. node_modules/
    5. public/js/
    6. public/css/
    7. yarn-error.log
    8. bootstrap/cache/*
    9. storage/
    10. # 自行添加其他需要排除的文件,例如 .env.* 文件

    laravel.conf 文件中写入 nginx 配置。

    1. server {
    2. listen 80 default_server;
    3. root /app/laravel/public;
    4. index index.php index.html;
    5. location / {
    6. try_files $uri $uri/ /index.php?$query_string;
    7. }
    8. location ~ .*\.php(\/.*)*$ {
    9. fastcgi_pass laravel:9000;
    10. include fastcgi.conf;
    11. # fastcgi_connect_timeout 300;
    12. # fastcgi_send_timeout 300;
    13. # fastcgi_read_timeout 300;
    14. }
    15. }

    前端构建

    第一阶段进行前端构建。

    1. FROM node:alpine as frontend
    2. COPY package.json /app/
    3. RUN cd /app \
    4. && npm install --registry=https://registry.npm.taobao.org
    5. COPY webpack.mix.js /app/
    6. COPY resources/assets/ /app/resources/assets/
    7. RUN cd /app \
    8. && npm run production

    安装 Composer 依赖

    第二阶段安装 Composer 依赖。

    1. FROM composer as composer
    2. COPY database/ /app/database/
    3. COPY composer.json composer.lock /app/
    4. RUN cd /app \
    5. && composer config -g repo.packagist composer https://packagist.laravel-china.org \
    6. && composer install \
    7. --ignore-platform-reqs \
    8. --no-interaction \
    9. --no-plugins \
    10. --no-scripts \
    11. --prefer-dist

    整合以上阶段所生成的文件

    第三阶段对以上阶段生成的文件进行整合。

    1. FROM php:7.2-fpm-alpine as laravel
    2. ARG LARAVEL_PATH=/app/laravel
    3. COPY --from=composer /app/vendor/ ${LARAVEL_PATH}/vendor/
    4. COPY . ${LARAVEL_PATH}
    5. COPY --from=frontend /app/public/js/ ${LARAVEL_PATH}/public/js/
    6. COPY --from=frontend /app/public/css/ ${LARAVEL_PATH}/public/css/
    7. COPY --from=frontend /app/mix-manifest.json ${LARAVEL_PATH}/mix-manifest.json
    8. RUN cd ${LARAVEL_PATH} \
    9. && php artisan package:discover \
    10. && mkdir -p storage \
    11. && mkdir -p storage/framework/cache \
    12. && mkdir -p storage/framework/sessions \
    13. && mkdir -p storage/framework/testing \
    14. && mkdir -p storage/framework/views \
    15. && mkdir -p storage/logs \
    16. && chmod -R 777 storage

    最后一个阶段构建 NGINX 镜像

    1. FROM nginx:alpine as nginx
    2. ARG LARAVEL_PATH=/app/laravel
    3. COPY laravel.conf /etc/nginx/conf.d/
    4. COPY --from=laravel ${LARAVEL_PATH}/public ${LARAVEL_PATH}/public

    构建 Laravel 及 Nginx 镜像

    使用 docker build 命令构建镜像。

    1. $ docker build -t my/laravel --target=laravel .
    2. $ docker build -t my/nginx --target=nginx .

    启动容器并测试

    新建 Docker 网络

    1. $ docker network create laravel

    启动 laravel 容器, --name=laravel 参数设定的名字必须与 nginx 配置文件中的 fastcgi_pass laravel:9000; 一致

    1. $ docker run -it --rm --name=laravel --network=laravel my/laravel

    启动 nginx 容器

    1. $ docker run -it --rm --network=laravel -p 8080:80 my/nginx

    浏览器访问 127.0.0.1:8080 可以看到 Laravel 项目首页。

    也许 Laravel 项目依赖其他外部服务,例如 redis、MySQL,请自行启动这些服务之后再进行测试,本小节不再赘述。

    生产环境优化

    本小节内容为了方便测试,将配置文件直接放到了镜像中,实际在使用时 建议 将配置文件作为 configsecret 挂载到容器中,请读者自行学习 Swarm modeKubernetes 的相关内容。

    附录

    完整的 Dockerfile 文件如下。

    1. FROM node:alpine as frontend
    2. COPY package.json /app/
    3. RUN cd /app \
    4. && npm install --registry=https://registry.npm.taobao.org
    5. COPY webpack.mix.js /app/
    6. COPY resources/assets/ /app/resources/assets/
    7. RUN cd /app \
    8. && npm run production
    9. FROM composer as composer
    10. COPY database/ /app/database/
    11. COPY composer.json /app/
    12. RUN cd /app \
    13. && composer config -g repo.packagist composer https://packagist.laravel-china.org \
    14. && composer install \
    15. --ignore-platform-reqs \
    16. --no-interaction \
    17. --no-plugins \
    18. --no-scripts \
    19. --prefer-dist
    20. FROM php:7.2-fpm-alpine as laravel
    21. ARG LARAVEL_PATH=/app/laravel
    22. COPY --from=composer /app/vendor/ ${LARAVEL_PATH}/vendor/
    23. COPY . ${LARAVEL_PATH}
    24. COPY --from=frontend /app/public/js/ ${LARAVEL_PATH}/public/js/
    25. COPY --from=frontend /app/public/css/ ${LARAVEL_PATH}/public/css/
    26. COPY --from=frontend /app/mix-manifest.json ${LARAVEL_PATH}/mix-manifest.json
    27. RUN cd ${LARAVEL_PATH} \
    28. && php artisan package:discover \
    29. && mkdir -p storage \
    30. && mkdir -p storage/framework/cache \
    31. && mkdir -p storage/framework/sessions \
    32. && mkdir -p storage/framework/testing \
    33. && mkdir -p storage/framework/views \
    34. && mkdir -p storage/logs \
    35. && chmod -R 777 storage
    36. FROM nginx:alpine as nginx
    37. ARG LARAVEL_PATH=/app/laravel
    38. COPY laravel.conf /etc/nginx/conf.d/
    39. COPY --from=laravel ${LARAVEL_PATH}/public ${LARAVEL_PATH}/public