尝试使用 docker 部署 Laravel 项目

环境: ubnutu18.04 虚拟机上通过 docker 部署,首先需要安装好 docker 环境
安装 docker

docker 镜像要求

  • 基于 Alpine Linux 的容器。
  • Nginx Web 服务器。
  • PHP 7.0 或更高版本。
  • OpenSSL PHP 扩展。
  • PDO PHP 扩展。
  • Mbstring PHP 扩展。
  • Tokenizer PHP 扩展。
  • XML PHP 扩展。

1. 创建 laradocker 目录#

mkdir laradocker

2. 进入目录 cd laradocker 创建 Dockerfile 文件 vim Dockerfile#

FROM nginx:mainline-alpine
LABEL maintainer="Jaak zhang <xxxx@163.come>" 

COPY start.sh /start.sh
COPY nginx.conf /etc/nginx/nginx.conf
COPY supervisord.conf /etc/supervisord.conf
COPY site.conf /etc/nginx/sites-available/default.conf

RUN echo "#aliyun" > /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/v3.10/main/" >> /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/v3.10/community/" >> /etc/apk/repositories
RUN apk update

RUN apk add --update curl  php7-fpm php7  php7-dev  php7-apcu  php7-bcmath  php7-xmlwriter  php7-ctype  php7-curl  php7-exif  php7-iconv  php7-intl  php7-json  php7-mbstring php7-opcache  php7-openssl  php7-pcntl  php7-pdo  php7-mysqlnd  php7-mysqli  php7-pdo_mysql  php7-pdo_pgsql  php7-phar  php7-posix  php7-session  php7-xml  php7-simplexml  php7-mcrypt  php7-xsl  php7-zip  php7-zlib  php7-dom  php7-redis php7-tokenizer  php7-gd  php7-fileinfo  php7-zmq  php7-memcached  php7-xmlreader 

RUN curl -sS https://getcomposer.org/installer | \
php -- --install-dir=/usr/bin/ --filename=composer

RUN apk add --update bash vim openssh-client supervisor

RUN mkdir -p /etc/nginx && \
mkdir -p /etc/nginx/sites-available && \
mkdir -p /etc/nginx/sites-enabled && \
mkdir -p /run/nginx && \
ln -s /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/default.conf && \
mkdir -p /var/log/supervisor && \
rm -Rf /var/www/* && \
chmod 755 /start.sh

RUN sed -i -e "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g" \
-e "s/variables_order = \"GPCS\"/variables_order = \"EGPCS\"/g" \
/etc/php7/php.ini && \
sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" \
-e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" \
-e "s/user = nobody/user = nginx/g" \
-e "s/group = nobody/group = nginx/g" \
-e "s/;listen.mode = 0660/listen.mode = 0666/g" \
-e "s/;listen.owner = nobody/listen.owner = nginx/g" \
-e "s/;listen.group = nobody/listen.group = nginx/g" \
-e "s/listen = 127.0.0.1:9000/listen = \/var\/run\/php-fpm.sock/g" \
-e "s/^;clear_env = no$/clear_env = no/" \
/etc/php7/php-fpm.d/www.conf

EXPOSE 443 80
WORKDIR /var/www

CMD ["/start.sh"]

3. laradocker 目录下创建 start.sh 文件; vim start.sh#

#!/bin/bash

# ----------------------------------------------------------------------
# Create the .env file if it does not exist.
# ----------------------------------------------------------------------
if [[ ! -f "/var/www/.env" ]] && [[ -f "/var/www/.env.example" ]];
then
    cp /var/www/.env.example /var/www/.env
fi

# ----------------------------------------------------------------------
# Run Composer
# ----------------------------------------------------------------------
if [[ ! -d "/var/www/vendor" ]];
then
    cd /var/www
    composer update
    composer dump-autoload -o
fi

# ----------------------------------------------------------------------
# Start supervisord
# ----------------------------------------------------------------------
exec /usr/bin/supervisord -n -c /etc/supervisord.conf

4. laradocker 目录下创建 nginx.conf 文件; vim nginx.conf#

user nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log off;
    sendfile on;
    #tcp_nopush on;
    keepalive_timeout 65;
    #gzip on;
    include /etc/nginx/sites-enabled/*.conf;
}

5. 同样创建 site.conf 文件 vim site.conf#

server {
    listen 80;

    root /var/www/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ /\. {
        deny all;
    }

    location ~ \.php$ {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

6. 创建 supervisord.conf 文件#


[unix_http_server]
file=/dev/shm/supervisor.sock

[supervisord]
logfile=/tmp/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=warn
pidfile=/tmp/supervisord.pid
nodaemon=false
minfds=1024
minprocs=200
user=root

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock

[program:php-fpm7]
command = /usr/sbin/php-fpm7 --nodaemonize --fpm-config /etc/php7/php-fpm.d/www.conf
autostart=true
autorestart=true
priority=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
priority=10
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

7. laradocker 目录下创建 src 文件夹 把你的 laravel 项目代码 git clone 下来 或者 cpoy 进去; laradocker 执行 ls 应该是下面几个目录文件#

root@localhost:~/laraDocker# ls
Dockerfile  nginx.conf  site.conf  src  start.sh  supervisord.conf
root@localhost:~/laraDocker# cd src/
root@localhost:~/laraDocker/src# ls
blog
# 这里我clone下来的是个blog项目

8. 构建 docker 镜像#

$ docker build -t  my-image .

9. 容器运行,终端上运行以下命令:#

# 将`$PWD/src`目录挂载到`/var/www`容器中。`$PWD`将返回到当前工作目录的路径。
$ docker run -d -p 8000:80 -v $PWD/src/blog:/var/www --name="container-lara" my-image

10. 访问你的虚拟机 IP + 端口号 8000, 我的是 http://192.168.8.225:8000#

出现错误 是 laravel 项目的 key 没有,执行命令 docker exec -it container-lara bash 进入容器
这里其实也可以在 start.sh 文件中先加入 php artisan key:generate 命令

root@localhost:~/laraDocker# docker exec -it container-lara bash
bash-5.0# ls
LICENSE            bootstrap          database           phpcs.sh           routes             vendor
README.md          composer.json      frontend           phpunit.xml        server.php         webpack.mix.js
app                composer.lock      package-lock.json  public             storage
artisan            config             package.json       resources          tests
bash-5.0# pwd
/var/www
bash-5.0# php artisan key:generate
Application key [base64:Br4OjMwsByCHcL797l/eyTu9V+gYTWnL+YgShopHTzI=] set successfully.
bash-5.0# 

依然报错是因为 mysql 问题 没有安装 mysql
使用 docker 拉取 mysql 镜像

  • 执行命令 docker pull mysql:5.7
  • 运行 mysql 容器 执行命令
    docker run -d -p 3306:3306 --name db-mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=blog -d mysql:5.7
  • 修改 src 目录下 blog 项目目录下.env 文件中 mysql 相关配置即可

项目有用到 redis,docker 拉取 redis 镜像

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
jaak
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 19

RUN 部分可以合并、可以减小构建镜像的大小,对指令会将镜像分层增加从而增加镜像的大小。构建开发可以分多个,这样的话、推荐构建基础镜像。

5年前 评论
jaak (楼主) 5年前

有没有用过 laradock, 怎么让同一个局域网的同事访问我的项目

5年前 评论
Tricker 5年前
Tricker 5年前
walt-white (作者) 5年前
walt-white (作者) 5年前
jaak

@walt-white 没有用过,我觉得你可以试试在你同事的电脑上修改 host 文件 添加上你的项目 ip 域名,然后域名访问

5年前 评论
walt-white 5年前

请问大佬,我按照流程跑了一遍之后,发现我的工程不能连接 mysql,报错为

SQLSTATE[HY000] [2002] No such file or directory

是不是因为我 mysql 的 docker 没有把 mysql.sock 映射出来,从而我的 Laradocker 不能访问我的 mysql docker

5年前 评论
jaak (楼主) 5年前
walt-white 5年前
php8 5年前
ShibaPipi (作者) 5年前

感觉好难啊,像黑客在秀操作。

5年前 评论
jaak (楼主) 5年前

:thumbsup: 非常好的文章,学习了,谢谢!

4年前 评论

非常感谢楼主大佬的文章!根据楼主老哥大佬的修改的 laravel6.x+php7.4 + 项目代码 + laravel 计划任务,k8s 部署,容器不能连外网,所以没装 composer,取而代之的是把代码整个放入容器内,日志、文件目录映射到宿主机,供参考
Dockerfile:

FROM nginx:mainline-alpine

COPY start.sh /start.sh
COPY nginx.conf /etc/nginx/nginx.conf
COPY supervisord.conf /etc/supervisord.conf
COPY site.conf /etc/nginx/sites-available/default.conf
COPY src/feedback /var/www

RUN echo "#aliyun" > /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/v3.13/main/" >> /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/v3.13/community/" >> /etc/apk/repositories
RUN apk update

RUN apk add --update curl  php7-fpm php7  php7-dev  php7-apcu  php7-bcmath  php7-xmlwriter  php7-ctype  php7-curl  php7-exif  php7-iconv  php7-intl  php7-json  php7-mbstring php7-opcache  php7-openssl  php7-pcntl  php7-pdo  php7-mysqlnd  php7-mysqli  php7-pdo_mysql  php7-pdo_pgsql  php7-phar  php7-posix  php7-session  php7-xml  php7-simplexml  php7-mcrypt  php7-xsl  php7-zip  php7-zlib  php7-dom  php7-redis php7-tokenizer  php7-gd  php7-fileinfo  php7-zmq  php7-memcached  php7-xmlreader 

RUN apk add --update bash vim openssh-client supervisor

RUN mkdir -p /etc/nginx && \
mkdir -p /etc/nginx/sites-available && \
mkdir -p /etc/nginx/sites-enabled && \
mkdir -p /run/nginx && \
ln -s /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/default.conf && \
mkdir -p /var/log/supervisor && \
chmod 755 /start.sh  && \
chmod -R 777 /var/www

RUN sed -i -e "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g" \
-e "s/variables_order = \"GPCS\"/variables_order = \"EGPCS\"/g" \
/etc/php7/php.ini && \
sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" \
-e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" \
-e "s/user = nobody/user = nginx/g" \
-e "s/group = nobody/group = nginx/g" \
-e "s/;listen.mode = 0660/listen.mode = 0666/g" \
-e "s/;listen.owner = nobody/listen.owner = nginx/g" \
-e "s/;listen.group = nobody/listen.group = nginx/g" \
-e "s/listen = 127.0.0.1:9000/listen = \/var\/run\/php-fpm.sock/g" \
-e "s/^;clear_env = no$/clear_env = no/" \
/etc/php7/php-fpm.d/www.conf

EXPOSE 443 80
WORKDIR /var/www

CMD ["/start.sh"]

start.sh

#!/bin/bash

# ----------------------------------------------------------------------
# Create the .env file if it does not exist.
# ----------------------------------------------------------------------
if [[ ! -f "/var/www/.env" ]] && [[ -f "/var/www/.env.example" ]];
then
    cp /var/www/.env.example /var/www/.env
fi

# laravel定时任务,App\Console\Kernel.php中编写,见laravel文档
sed -i '$d' /etc/crontabs/root
echo '*       *       *       *       *       cd /var/www && php artisan schedule:run >> /dev/null 2>&1' >> /etc/crontabs/root
echo '' >> /etc/crontabs/root
crond

# ----------------------------------------------------------------------
# Start supervisord
# ----------------------------------------------------------------------
exec /usr/bin/supervisord -n -c /etc/supervisord.conf

(可选)进入容器验证计划任务是否正常运行:

ps # 查看是否有crond
cat /etc/crontabs/root # 查看laravel计划任务是否正常添加

容器⇌宿主机 映射:
/var/www/public/storage
/var/www/storage/app/public
k8s 容器貌似不能 link 操作,我取而代之的是上面这两个映射到宿主机的同一个目录
/var/log
/var/www/storage/logs
/var/www/.env

4年前 评论

请问如何用 dockerfile 安装 php8 呢?

2年前 评论