个人用Docker网站部署的一些记录,主要内容是 Nginx 配置以及 docker-compose.yml 配置

数据库

MySQL

因为 LskyPro 图床 2.0 需要 MySQL 版本>=5.7,所以装了 MySQL 5.7 ,docker-compose.yml配置如下:

mysql:
  image: mysql:5.7
  restart: always
  environment:
    - TZ=Asia/Shanghai
    #root密码
    - MYSQL_ROOT_PASSWORD=remove_for_privacy
  expose:
    - "3306"
  volumes:
  #MySQL数据目录
    - ./mysql/data:/var/lib/mysql
  command:
    [
      'mysqld',
      #设置默认编码
      '--character-set-server=utf8mb4',
      '--collation-server=utf8mb4_unicode_ci'
    ]
  container_name: mysql
  networks:
    - web

phpMyAdmin

选用了老牌的 phpMyAdmin 作为数据库管理工具,docker-compose.yml 配置:

这里直接将 pma 暴露在了宿主机公网的8080端口上,如果 root 或其他数据库账户的密码较弱这样的行为非常不安全!!!建议将ports配置项删除,使用nginx反代 pma:80 并进行访问控制。

phpmyadmin:
  image: phpmyadmin:5.2.0-apache
  ports:
  #将pma暴露到服务器8080端口,不安全
    - "8080:80" 
  restart: always
  environment:
  #MySQL容器的container_name
    - PMA_HOST=mysql
  container_name: pma
  networks:
    - web

PHP

PHP 7.4

Typecho 和自留地目前用的主题对 PHP8 的支持都不太行,所以这部分还是使用 PHP7.4 来运行,在根目录新建php74文件夹,加入Dockerfile文件:

FROM php:7.4-fpm-alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
    && apk update \
    && docker-php-ext-install pdo_mysql \
    && curl -sS https://getcomposer.org/installer | php \
    && mv composer.phar /usr/local/bin/composer \
    && apk add --no-cache git

docker-compose.yml配置:

php74:
  build: php74
  restart: always
  expose:
    - "9000"
  volumes:
    #网站文件根目录
    - ./website:/var/www/html
    #PHP7.4数据目录
    - ./php74/config:/usr/local/etc/php
  environment:
    - TZ=Asia/Shanghai
  depends_on:
    - mysql
  container_name: php74
  networks:
    - web

PHP 8.0

因为LskyPro图床硬性要求 PHP 8还有一大堆拓展,这里照抄了mikusa大佬的适用于 LskyPro 的 PHP8 Dockerfile,在根目录新建php80文件夹,加入Dockerfile文件:

FROM php:8.0-fpm-alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
    && apk update \
    && apk add --virtual .build-tools --no-cache autoconf gcc g++ make \
    && apk --no-cache add ffmpeg graphicsmagick zip zlib-dev libjpeg-turbo-dev libpng-dev freetype-dev imagemagick-dev imagemagick libzip-dev icu-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd \
    && docker-php-ext-install exif mysqli pdo_mysql zip bcmath intl pcntl \
    && pecl install redis imagick \
    && docker-php-ext-enable redis imagick \
    && apk del .build-tools \
    && curl -sS https://getcomposer.org/installer | php \
    && mv composer.phar /usr/local/bin/composer \
    && apk add --no-cache git

docker-compose.yml中加入配置:

php80:
  build: php80
  restart: always
  expose:
    - "9000"
  volumes:
    #网站文件根目录
    - ./website:/var/www/html
    #PHP8.0数据目录
    - ./php80/config:/usr/local/etc/php
  environment:
    - TZ=Asia/Shanghai
  depends_on:
    - mysql
  container_name: php80
  networks:
    - web

Nginx

Nginx配置

基本上是抄的宝塔的Nginx配置,nginx.conf配置:

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
worker_rlimit_nofile 51200;

events {
    use epoll;
    worker_connections 51200;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    include proxy.conf;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    server_names_hash_bucket_size 512;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 50m;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 60;

    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;

    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 2;
    gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
    gzip_vary on;
    gzip_proxied expired no-cache no-store private auth;
    gzip_disable "MSIE [1-6]\.";

    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;

    access_log /var/log/nginx/access.log main;

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

docker-compose.yml 配置:

nginx:
  image: nginx
  ports:
    - "80:80"
    - "443:443"
  restart: always
  environment:
    - TZ=Asia/Shanghai
  volumes:
    #网站文件根目录
    - ./website:/var/www/html
    #Nginx数据目录
    - ./nginx:/etc/nginx
    #Nginx日志目录
    - ./logs:/var/log/nginx
  depends_on:
    - acme.sh
    - php74
    - php80
  container_name: nginx
  labels:
    - nginx.main
  networks:
    - web

网站配置

也是基本照抄宝塔配置

使用PHP7.4的网站引入该文件,php74.conf

location ~ \.php(.*)$ {
    fastcgi_pass php74:9000;
    fastcgi_index index.php;
    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
    fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

使用PHP8.0的网站引入该文件,php80.conf

location ~ \.php(.*)$ {
    fastcgi_pass php80:9000;
    fastcgi_index index.php;
    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
    fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

SSL配置,ssl.conf

ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;

HTTPS自动跳转配置,https.conf

if ($server_port !~ 443) {
    rewrite ^(/.*)$ https://$host$1 permanent;
}

网站配置示例,example.com.conf

server {
    listen 80;
    listen 443 ssl http2;
    server_name example.com;
    root /var/www/html/example.com;
    index index.php index.html;

    # ssl
    ssl_certificate /etc/nginx/ssl/example.com/full.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/key.pem;
    include ssl.conf;

    # rewrite
    include /etc/nginx/rewrite/https.conf;
    include /etc/nginx/rewrite/typecho.conf;

    # other
    include php74.conf;

    access_log /var/log/nginx/access/example.com.log;
    error_log /var/log/nginx/error/example.com.log;
}

反代配置

反代网站配置,example.com.proxy.conf

location ^~ / {
    proxy_pass http://ip:port;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;

    add_header X-Cache $upstream_cache_status;
}

SSL

使用acme.sh申请泛域名证书,使用daemon模式自动刷新证书并自动部署到Nginx中

acme:
  image: neilpang/acme.sh:latest
  restart: always
  container_name: acme
  #使用daemon模式运行
  command: daemon
  volumes:
    - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
    - /var/run/docker.sock:/var/run/docker.sock
    #acme.sh数据目录
    - ./acme:/acme.sh
  environment:
    #使用DNSPod提供的API进行域名验证
    - DP_Id=remove_for_privacy
    - DP_Key=remove_for_privacy
    #Nginx容器的labels
    - DEPLOY_DOCKER_CONTAINER_LABEL=nginx.main
    #证书在Nginx中保存的路径
    - DEPLOY_DOCKER_CONTAINER_KEY_FILE=/etc/nginx/ssl/example.com/key.pem
    - DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/ssl/example.com/cert.pem"
    - DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/ssl/example.com/ca.pem"
    - DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/ssl/example.com/full.pem"
    #重载Nginx配置
    - DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="nginx -s reload"