使用 docker 以及 docker-compose 部署你的 Laravel 8 项目

东方弘壮
2023-12-01

安装 docker 以及 docker-compose

详见本人之前写的另一篇文章:Docker操作命令小助手

安装 Laravel

确保你的终端已经安装了 PHP 和 Composer,然后执行以下命令创建一个新的 Laravel 项目。当应用程序创建完成后,你可以通过 Artisan CLI 的 serve 命令来启动 Laravel 的本地服务测试服务是否正常

composer create-project laravel/laravel example-app

cd example-app

php artisan serve

构建镜像

本次构建使用的镜像为:richarvey/nginx-php-fpm,更新版本请前往该项目的Github

  • 第一步:在刚刚创建的 Laravel 项目根目录创建一个conf文件夹(其内再创建一个ssl二级目录,存放ssl证书,这里不在表述,本项目完整代码在文章最下方github地址完全可看),用来存放ngxin配置文件以及supervisord配置文件,分别取名为 nginx.confnginx-site.confnginx-site-ssl.confsupervisord.conf 输入内容分别如下:

nginx.conf

#user  nobody;
worker_processes auto;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    client_header_buffer_size 4k;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout 2;
	client_max_body_size 25m;

    server_tokens off;
    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

nginx-site.conf

server {
    listen 80;
    server_name laravel.com;
    root /var/www/html/public;
       index index.php index.html index.htm;

    error_log    /var/log/nginx/error_laravel.log    error;
    access_log   /var/log/nginx/access_laravel.log;

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

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

    location ~ .*\.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$ {
        expires 2d;
    }

    location ~ .*\.(?:js|css)$ {
        expires 8h;
    }

    location ~ /\. {
            log_not_found off;
            deny all;
        }
}

nginx-site-ssl.conf

server {
	listen 443 ssl http2;
    server_name _;
	root /var/www/html/public;
	index index.php index.html index.htm;

    ssl_certificate    /etc/nginx/ssl/_.pem;
    sl_certificate_key /etc/nginx/ssl/_.key;
    ssl_session_cache  shared:SSL:1m;
    ssl_session_timeout 10m;
    ssl_protocols       TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

	# Make site accessible from http://localhost/

	# Add stdout logging
	error_log    /var/log/nginx/error_laravel.log    error;
    access_log   /var/log/nginx/access_laravel.log;

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

	error_page 404 /404.html;
       location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }

	# pass the PHP scripts to FastCGI server listening on socket
	#
	location ~ \.php$ {
        try_files $uri =404;
		fastcgi_split_path_info ^(.+\.php)(/.+)$;
		fastcgi_pass unix:/var/run/php-fpm.sock;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
		fastcgi_index index.php;
		include fastcgi_params;
	}

    location ~* \.(jpg|jpeg|gif|png|css|js|ico|webp|tiff|ttf|svg)$ {
         expires   5d;
    }

	# deny access to . files, for security
	#
	location ~ /\. {
    		log_not_found off;
    		deny all;
	}

	location ^~ /.well-known {
                allow all;
                auth_basic off;
        }

}

supervisord.conf

[unix_http_server]
file=/dev/shm/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
loglevel=info                ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024)
minprocs=200                 ; (min. avail process descriptors;default 200)
user=root		     ;

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock ; use a unix:// URL  for a unix socket

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

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

[program:queue-work]
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3 --timeout=85 --daemon
autostart=true
autorestart=true
priority=5
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
stopsignal=QUIT

[include]
files = /etc/supervisor/conf.d/*.conf
  • 第二步:同样在项目根目录创建一个 Dockerfile 文件,输入以下内容
FROM richarvey/nginx-php-fpm:1.10.4

RUN sed -i "s/pm.max_children = [0-9]\+/pm.max_children = 64/g" /usr/local/etc/php-fpm.d/www.conf \
    && sed -i "s/pm.start_servers = [0-9]\+/pm.start_servers = 8/g" /usr/local/etc/php-fpm.d/www.conf \
    && sed -i "s/pm.min_spare_servers = [0-9]\+/pm.min_spare_servers = 8/g" /usr/local/etc/php-fpm.d/www.conf \
    && sed -i "s/pm.max_spare_servers = [0-9]\+/pm.max_spare_servers = 32/g" /usr/local/etc/php-fpm.d/www.conf \
    && cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \
    && sed -i 's/session.save_handler = files/session.save_handler = redis\nsession.save_path = "tcp:\/\/redis:6379"/g' /usr/local/etc/php/php.ini \
    && sed -i 's/session.gc_maxlifetime = 1440/session.gc_maxlifetime = 14400/g' /usr/local/etc/php/php.ini \
    && sed -i 's/memory_limit = 128M/memory_limit = 512M/g' /usr/local/etc/php/conf.d/docker-vars.ini \
    && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && apk add --no-cache lua-resty-core nginx-mod-http-lua \
    && docker-php-ext-install sockets bcmath

# Copy our nginx config
RUN rm -Rf /etc/nginx/nginx.conf
COPY conf/nginx.conf /etc/nginx/nginx.conf
COPY conf/nginx-site.conf /etc/nginx/conf.d/default.conf
COPY conf/nginx-site-ssl.conf /etc/nginx/conf.d/default-ssl.conf

# Copy our nginx ssl
COPY conf/ssl /etc/nginx/ssl

# Copy our supervisord config
COPY conf/supervisord.conf /etc/supervisord.conf

# Copy our shell
COPY start.sh /start.sh

COPY . /var/www/html

RUN cd /var/www/html \
    && composer install -o --no-dev \
    && cp .env.local .env \
    && chown -Rf nginx.nginx /var/www/html \
    && chmod +x /start.sh

EXPOSE 443 80

WORKDIR /var/www/html

CMD ["/start.sh"]
  • 第三步:同样在项目根目录创建 shell 脚本文件 start.sh,输入内容如下
#!/bin/bash

# Set custom webroot
if [ ! -z "$WEBROOT" ]; then
 sed -i "s#root /var/www/html;#root ${WEBROOT};#g" /etc/nginx/conf.d/default.conf
else
 webroot=/var/www/html
fi

# Enables 404 pages through php index
if [ ! -z "$PHP_CATCHALL" ]; then
 sed -i 's#try_files $uri $uri/ =404;#try_files $uri $uri/ /index.php?$args;#g' /etc/nginx/conf.d/default.conf
fi

# Enable custom nginx config files if they exist
if [ -f /var/www/html/conf/nginx/nginx.conf ]; then
  cp /var/www/html/conf/nginx/nginx.conf /etc/nginx/nginx.conf
fi

if [ -f /var/www/html/conf/nginx/nginx-site.conf ]; then
  cp /var/www/html/conf/nginx/nginx-site.conf /etc/nginx/conf.d/default.conf
fi

if [ -f /var/www/html/conf/nginx/nginx-site-ssl.conf ]; then
  cp /var/www/html/conf/nginx/nginx-site-ssl.conf /etc/nginx/conf.d/default-ssl.conf
fi

# Display PHP error's or not
if [[ "$ERRORS" != "1" ]] ; then
 echo php_flag[display_errors] = off >> /usr/local/etc/php-fpm.d/www.conf
else
 echo php_flag[display_errors] = on >> /usr/local/etc/php-fpm.d/www.conf
fi

# Display Version Details or not
if [[ "$HIDE_NGINX_HEADERS" == "0" ]] ; then
 sed -i "s/server_tokens off;/server_tokens on;/g" /etc/nginx/nginx.conf
else
 sed -i "s/expose_php = On/expose_php = Off/g" /usr/local/etc/php-fpm.conf
fi

# Pass real-ip to logs when behind ELB, etc
if [[ "$REAL_IP_HEADER" == "1" ]] ; then
 sed -i "s/#real_ip_header X-Forwarded-For;/real_ip_header X-Forwarded-For;/" /etc/nginx/conf.d/default.conf
 sed -i "s/#set_real_ip_from/set_real_ip_from/" /etc/nginx/conf.d/default.conf
 if [ ! -z "$REAL_IP_FROM" ]; then
  sed -i "s#172.16.0.0/12#$REAL_IP_FROM#" /etc/nginx/conf.d/default.conf
 fi
fi

# Do the same for SSL sites
if [ -f /etc/nginx/conf.d/default-ssl.conf ]; then
 if [[ "$REAL_IP_HEADER" == "1" ]] ; then
  sed -i "s/#real_ip_header X-Forwarded-For;/real_ip_header X-Forwarded-For;/" /etc/nginx/conf.d/default-ssl.conf
  sed -i "s/#set_real_ip_from/set_real_ip_from/" /etc/nginx/conf.d/default-ssl.conf
  if [ ! -z "$REAL_IP_FROM" ]; then
   sed -i "s#172.16.0.0/12#$REAL_IP_FROM#" /etc/nginx/conf.d/default-ssl.conf
  fi
 fi
fi

# Set the desired timezone
echo date.timezone=$(cat /etc/TZ) > /usr/local/etc/php/conf.d/timezone.ini

# Display errors in docker logs
if [ ! -z "$PHP_ERRORS_STDERR" ]; then
  echo "log_errors = On" >> /usr/local/etc/php/conf.d/docker-vars.ini
  echo "error_log = /dev/stderr" >> /usr/local/etc/php/conf.d/docker-vars.ini
fi

# Increase the memory_limit
if [ ! -z "$PHP_MEM_LIMIT" ]; then
 sed -i "s/memory_limit = 128M/memory_limit = ${PHP_MEM_LIMIT}M/g" /usr/local/etc/php/conf.d/docker-vars.ini
fi

# Increase the post_max_size
if [ ! -z "$PHP_POST_MAX_SIZE" ]; then
 sed -i "s/post_max_size = 100M/post_max_size = ${PHP_POST_MAX_SIZE}M/g" /usr/local/etc/php/conf.d/docker-vars.ini
fi

# Increase the upload_max_filesize
if [ ! -z "$PHP_UPLOAD_MAX_FILESIZE" ]; then
 sed -i "s/upload_max_filesize = 100M/upload_max_filesize= ${PHP_UPLOAD_MAX_FILESIZE}M/g" /usr/local/etc/php/conf.d/docker-vars.ini
fi

# Enable xdebug
XdebugFile='/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini'
if [[ "$ENABLE_XDEBUG" == "1" ]] ; then
  if [ -f $XdebugFile ]; then
  	echo "Xdebug enabled"
  else
  	echo "Enabling xdebug"
  	echo "If you get this error, you can safely ignore it: /usr/local/bin/docker-php-ext-enable: line 83: nm: not found"
  	# see https://github.com/docker-library/php/pull/420
    docker-php-ext-enable xdebug
    # see if file exists
    if [ -f $XdebugFile ]; then
        # See if file contains xdebug text.
        if grep -q xdebug.remote_enable "$XdebugFile"; then
            echo "Xdebug already enabled... skipping"
        else
            echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > $XdebugFile # Note, single arrow to overwrite file.
            echo "xdebug.remote_enable=1 "  >> $XdebugFile
            echo "xdebug.remote_host=host.docker.internal" >> $XdebugFile
            echo "xdebug.remote_log=/tmp/xdebug.log"  >> $XdebugFile
            echo "xdebug.remote_autostart=false "  >> $XdebugFile # I use the xdebug chrome extension instead of using autostart
            # NOTE: xdebug.remote_host is not needed here if you set an environment variable in docker-compose like so `- XDEBUG_CONFIG=remote_host=192.168.111.27`.
            #       you also need to set an env var `- PHP_IDE_CONFIG=serverName=docker`
        fi
    fi
  fi
else
    if [ -f $XdebugFile ]; then
        echo "Disabling Xdebug"
      rm $XdebugFile
    fi
fi

if [ ! -z "$PUID" ]; then
  if [ -z "$PGID" ]; then
    PGID=${PUID}
  fi
  deluser nginx
  addgroup -g ${PGID} nginx
  adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx -u ${PUID} nginx
else
  if [ -z "$SKIP_CHOWN" ]; then
    chown -Rf nginx.nginx /var/www/html
  fi
fi

# Run custom scripts
if [[ "$RUN_SCRIPTS" == "1" ]] ; then
  if [ -d "/var/www/html/scripts/" ]; then
    # make scripts executable incase they aren't
    chmod -Rf 750 /var/www/html/scripts/*; sync;
    # run scripts in number order
    for i in `ls /var/www/html/scripts/`; do /var/www/html/scripts/$i ; done
  else
    echo "Can't find script directory"
  fi
fi

if [ -z "$SKIP_COMPOSER" ]; then
    # Allow nginx user to call composer closes #169
    # Try auto install for composer
    if [ -f "/var/www/html/composer.lock" ]; then
        if [ "$APPLICATION_ENV" == "development" ]; then
            su - nginx -c 'composer global require hirak/prestissimo'
            su - nginx -c 'composer install --working-dir=/var/www/html'
        else
            su - nginx -c 'composer global require hirak/prestissimo'
            su - nginx -c 'composer install --no-dev --working-dir=/var/www/html'
        fi
    fi
fi

# Start supervisord and services
exec /usr/bin/supervisord -n -c /etc/supervisord.conf
  • 第四步:同样在项目根目录创建 docker-compose.yml,输入内容如下
version: '3'
services:

  web:
    build:
      context: ./
      dockerfile: Dockerfile
    image: "xxx/laravelapp:8" #该处为了举例配置,是一个错误的镜像仓库,可自行将镜像上传仓库后配置
    container_name: "laravel_app"
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - redis
      - mysql
    links:
      - redis
      - mysql
    volumes:
      - "/home/web/storage:/var/www/html/storage"
      - "/etc/localtime:/etc/localtime"

  redis:
    image: "redis:alpine"
    container_name: "laravel_redis"
    restart: unless-stopped
    volumes:
      - "/home/web/redis:/data"
      - "/etc/localtime:/etc/localtime"

  mysql:
    image: mysql:8
    container_name: "laravel_mysql"
    security_opt:
      - seccomp:unconfined
    restart: unless-stopped
    volumes:
      - "/home/web/mysql/data/:/var/lib/mysql"
      - "/etc/localtime:/etc/localtime"
    environment:
      MYSQL_ROOT_PASSWORD: Pc4hzz.sf
    ports:
      - "3306:3306"

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: "laravel_phpmyadmin"
    restart: unless-stopped
    volumes:
      - "/etc/localtime:/etc/localtime"
    environment:
      - PMA_HOST=mysql
    depends_on:
      - mysql
    ports:
      - "8008:80"

运行项目

直接运行

docker-compose up -d

上传至 hub.docker.com仓库

# 打包镜像
docker build -t 你的仓库用户名/laravelapp:8 . 

# 登录
docker login

# 上传刚才打包的镜像
docker push 你的仓库用户名/laravelapp:8

# 通过docker-compose拉取镜像
docker-compose -f docker-compose.yml pull

# 启动
docker-compose up -d

#重启
docker-compose restart

访问项目

http://127.0.0.1:80 or http://127.0.0.1:443

Github

https://github.com/zl-php/laravelapp

 类似资料: