实战多阶段构建 Laravel 镜像

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

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

    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 依赖

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

    1. ARG LARAVEL_PATH=/app/laravel
    2. COPY --from=composer /app/vendor/ ${LARAVEL_PATH}/vendor/
    3. COPY --from=frontend /app/public/js/ ${LARAVEL_PATH}/public/js/
    4. COPY --from=frontend /app/public/css/ ${LARAVEL_PATH}/public/css/
    5. COPY --from=frontend /app/mix-manifest.json ${LARAVEL_PATH}/mix-manifest.json
    6. RUN cd ${LARAVEL_PATH} \
    7. && php artisan package:discover \
    8. && mkdir -p storage \
    9. && mkdir -p storage/framework/cache \
    10. && mkdir -p storage/framework/sessions \
    11. && mkdir -p storage/framework/testing \
    12. && mkdir -p storage/framework/views \
    13. && mkdir -p storage/logs \
    14. && 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 命令构建镜像。

    新建 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

    浏览器访问 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. && npm run production
    8. COPY database/ /app/database/
    9. COPY composer.json /app/
    10. RUN cd /app \
    11. && composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \
    12. && composer install \
    13. --ignore-platform-reqs \
    14. --no-interaction \
    15. --no-plugins \
    16. --no-scripts \
    17. --prefer-dist
    18. FROM php:7.2-fpm-alpine as laravel
    19. ARG LARAVEL_PATH=/app/laravel
    20. COPY --from=composer /app/vendor/ ${LARAVEL_PATH}/vendor/
    21. COPY . ${LARAVEL_PATH}
    22. COPY --from=frontend /app/public/js/ ${LARAVEL_PATH}/public/js/
    23. COPY --from=frontend /app/public/css/ ${LARAVEL_PATH}/public/css/
    24. COPY --from=frontend /app/mix-manifest.json ${LARAVEL_PATH}/mix-manifest.json
    25. RUN cd ${LARAVEL_PATH} \
    26. && php artisan package:discover \
    27. && mkdir -p storage \
    28. && mkdir -p storage/framework/cache \
    29. && mkdir -p storage/framework/sessions \
    30. && mkdir -p storage/framework/testing \
    31. && mkdir -p storage/framework/views \
    32. && mkdir -p storage/logs \
    33. && chmod -R 777 storage
    34. FROM nginx:alpine as nginx
    35. ARG LARAVEL_PATH=/app/laravel
    36. COPY laravel.conf /etc/nginx/conf.d/