搭建使用traefik

本文最后更新于 2023年9月22日。

1. 创建文件夹和文件

mkdir ~/traefik
cd ~/traefik
mkdir -p data/configurations
touch docker-compose.yml
touch data/traefik.yml
touch data/acme.json
touch data/configurations/dynamic.yml
chmod 600 data/acme.json

2. 配置 docker-compose.yml

文件路径为 ~/traefik/docker-compose.yml

version: '3.7'
services:
traefik:
image: traefik:v2.4
container_name: traefik
restart: always
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
volumes:
# 如果宿主机是标准 linux 系统,可以设置一下localtime
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro # 映射静态配置文件
- ./data/acme.json:/acme.json # 映射证书文件,SSL 证书申请成功后,就会存在这个文件中
- ./data/configurations:/configurations # 映射动态配置文件
networks:
- traefik
labels:
# 下面这些标签,可以帮助 traefik 正确处理该服务
- 'traefik.enable=true'
- 'traefik.docker.network=traefik' # 指定 docker network
# 指定服务入口为 websecure,websecure 会在静态配置文件traefik.yml中定义
- 'traefik.http.routers.traefik-secure.entrypoints=websecure'
# 定义访问域名,需要做 DNS 解析
- 'traefik.http.routers.traefik-secure.rule=Host(`traefik.yourdomain.com`)'
- 'traefik.http.routers.traefik-secure.middlewares=user-auth@file'
- 'traefik.http.routers.traefik-secure.service=api@internal'
networks:
traefik:
external: true

创建 docker-compose.yml 内需要的 network

docker network create traefik

3. 修改静态配置文件

文件路径为 ~/traefik/data/traefik.yml

api:
  dashboard: true
entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure
  websecure:
    address: :443
    http:
      middlewares:
        - secureHeaders@file
        - nofloc@file
      tls:
        certResolver: lets-encr
pilot:
  dashboard: false
providers:
  docker:
    endpoint: 'unix:///var/run/docker.sock'
    exposedByDefault: false
  file:
    filename: /configurations/dynamic.yml # 动态配置文件位置
certificatesResolvers:
  lets-encr:
    acme:
      #caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      storage: acme.json
      email: xxxxxx
      httpChallenge:
        entryPoint: web

4. 修改动态配置文件

文件路径为 ~/traefik/data/configurations/dynamic.yml

# Dynamic configuration
http:
middlewares:
nofloc:
headers:
customResponseHeaders:
Permissions-Policy: 'interest-cohort=()'
secureHeaders:
headers:
sslRedirect: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
# UserName : admin
# Password : qwer1234
user-auth:
basicAuth:
# users 选项是认证用户的列表
# 使用 echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
# 来创建 user:password 键值对
users:
- 'admin:$apr1$tm53ra6x$FntXd6jcvxYM/YH0P2hcc1'
tls:
options:
default:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
minVersion: VersionTLS12

5. 解析域名

在 docker-compose.yml 中,我们指定了使用 traefik.yourdomain.com 作为访问域名。因此,我们需要将 traefik.yourdomain.com 解析至 traefik 服务入口 IP 地址。

若使用单个云服务器部署 traefik,就需要将域名解析到服务器 IP 地址上

6. 启动服务

cd ~/traefik  # 确保位于 docker-compose.yml 所在目录
docker-compose up -d

7. 访问 Traefik Dashboard

在浏览器中访问 traefik.yourdomain.com,会发现自动加上了 SSL。
输入静态配置文件 dynamic.yml 中的用户名和密码,即可进入 Traefik Dashboard。
新建`whoami-docker-compose.yml

version: "3.7"
services:
  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.rule=Host(`whoami.weiyoun.com`)"
      - "traefik.http.routers.whoami.tls.certresolver=lets-encr"
networks:
  default:
    external:
      name: traefik

新建`cloudreve-docker-compose.yml

version: "3.7"
services:
  cloudreve:
    container_name: cloudreve
    image: cloudreve/cloudreve:latest
    restart: unless-stopped
    # ports:
      # - "5212:5212"
      # - "443:443"
    volumes:
      - cloudrevedata:/data
      - cloudreve:/cloudreve
      - cloudreveuploads:/cloudreve/uploads
      - cloudreveavatar:/cloudreve/avatar      
      # - ./cloudreve:/cloudreve # 221018 add ,error
      # - ./cloudreve/uploads:/cloudreve/uploads
      # - ./cloudreve/conf.ini:/cloudreve/conf.ini
      # - ./cloudreve/cloudreve.db:/cloudreve/cloudreve.db
      # - ./cloudreve/avatar:/cloudreve/avatar
  #   depends_on:
  #     - aria2
  # aria2:
  #   container_name: aria2
  #   image: p3terx/aria2-pro
  #   restart: unless-stopped
  #   environment:
  #     - RPC_SECRET=your_aria_rpc_token
  #     - RPC_PORT=6800
  #   volumes:
  #     - aria2Config:/config
  #     - tempData:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.cloudreve.entrypoints=websecure"
      # - "traefik.http.routers.cloudreve.entrypoints=web"
      - "traefik.http.routers.cloudreve.rule=Host(`yun.weiyoun.com`)"
      - "traefik.http.routers.cloudreve.tls.certresolver=lets-encr"
networks:
  default:
    external:
      name: traefik
volumes:
  cloudreve:
  cloudreveuploads:
  cloudrevedata:
  cloudreveavatar:

新建`kodcloud-docker-compose.yml

version: "3.7"
services:
  kodcloud:
    container_name: kodcloud
    image: kodcloud/kodbox
    restart: always
    # ports:
    #   - 1111:80
    volumes:
      - kodcloud:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.kodcloud.entrypoints=websecure"
      # - "traefik.http.routers.kodcloud.entrypoints=web"
      - "traefik.http.routers.kodcloud.rule=Host(`cloud.weiyoun.com`)"
      - "traefik.http.routers.kodcloud.tls.certresolver=lets-encr"
networks:
  default:
    external:
      name: traefik
volumes:
  kodcloud:

新建`lnmp-docker-compose.yml

version: "3.4"
volumes:
  # nextcloud:
  lnmpmariadb:
  lnmpphpConfig:
  lnmpnginxConf:
  lnmpnginxLog:
  lnmpnginxHtml:
services:
  mariadb:
    image: mariadb:10.5
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    ports:
      - "3306:3306"
    volumes:
      - lnmpmariadb:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=xxxxxx
      - MYSQL_PASSWORD=xxxxxx
      - MYSQL_DATABASE=user
      - MYSQL_USER=user
  # redis:
  #   image: redis
  #   restart: unless-stopped
  #   expose:
  #    - "6379"
  #   volumes:
  #    - redis:/data
  #   command: redis-server --requirepass 'redis_password' # 这里的redis_password换成你要配置的redis密码
  #   # command指的是启动容器后代替默认启动指令来启动服务的指令
  php:
    hostname: php
    restart: always
    image: php:8.1-new
    container_name: php
    build:
      context: ./php
      dockerfile: Dockerfile
    ports:
      - "9000:9000"
    links:
      - mariadb:mariadb
    volumes:
      - lnmpnginxHtml:/var/www/html
      - lnmpphpConfig:/usr/local/etc
    depends_on:
        # 依赖的容器列表,只有这些容器都成功启动了,才会启动当前容器
        - mariadb
        # - redis
  nginx:
    hostname: nginx
    restart: always
    container_name: nginx
    image: nginx:1.17.0
    ports:
      - "8080:80"
      # - "8443:8443"
    links:
      - "php:php"
      # - nextcloud:nextcloud
    volumes:
      - lnmpnginxConf:/etc/nginx
      # - ./nginx_config/conf.d:/etc/nginx/conf.d:ro
      # - ./nginx_config/ssl_certs:/etc/nginx/ssl_certs:ro
      - lnmpnginxLog:/var/log/nginx
      - lnmpnginxHtml:/usr/share/nginx/html  
      # - ./nextcloud/html:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.rule=Host(`www.weiyoun.com`)"
      - "traefik.http.routers.nginx.tls.certresolver=lets-encr"      
    depends_on:
     - php
networks:
  default:
    external:
      name: traefik

其中需要的php的dockerfile

FROM php:8.1.0RC5-fpm-buster
#buster是基于Debian Linux发行的一个版本,像PHP、Python之类的语言都会使用这个版本的Debian搭建Docker基础镜像。
#docker中php扩展安装方式
#1、PHP源码文件目录自带扩展 docker-php-ext-install直接安装
#2、pecl扩展 因为一些扩展不包含在PHP源码文件中,PHP 的扩展库仓库中存在。用 pecl install 安装扩展,再用 docker-php-ext-enable 命令 启用扩展
#3、其他扩展 一些既不在 PHP 源码包,也不再 PECL 扩展仓库中的扩展,可以通过下载扩展程序源码,编译安装的方式安装
#redis扩展 仓库地址 https://pecl.php.net/package/redis
ENV PHPREDIS_VERSION 5.3.4
#memcached扩展 仓库地址 https://pecl.php.net/package/memcached
ENV MEMCACHED_VERSION 3.1.5
#mongodb扩展 https://pecl.php.net/package/mongodb
ENV MONGODB_VERSION 1.11.1
# 设置时间
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo 'Asia/Shanghai' > /etc/timezone
# 221020 add 安装ImageMagick扩展 安装imagick扩展
# ENV IMAGICK_VERSION=3.4.4
# ENV IMAGEMAGICK_VERSION=7.0.10-39
# RUN apt-get update && apt-get install -y wget
# # 安装ImageMagick扩展
# RUN wget http://www.imagemagick.org/download/ImageMagick.tar.gz
# COPY extend/ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz /opt/ImageMagick.tar.gz
# RUN cd /opt/ && tar -zxvf ImageMagick.tar.gz \
#     && cd ImageMagick-${IMAGEMAGICK_VERSION} \
#     && ./configure --prefix=/usr/local/ImageMagick \
#     && make && make install
# 安装imagick扩展
# RUN wget http://pecl.php.net/get/imagick-3.4.4.tgz
# COPY extend/imagick-${IMAGICK_VERSION}.tgz /opt/imagick.tgz
# RUN docker-php-source extract \
#     && cd /opt/ && tar zxvf imagick.tgz && mv imagick-${IMAGICK_VERSION} /usr/src/php/ext/imagick \
#     && docker-php-ext-configure imagick --with-php-config=/usr/local/bin/php-config  --with-imagick=/usr/local/ImageMagick \
#     && docker-php-ext-install imagick
# RUN rm -rf /opt/*.tgz && rm -rf /opt/*.tar.gz
RUN apt-get update && apt-get install -y \
        # 221020 add libmagickwand-dev for imagick
        # libmagickwand-dev \
        # pecl install imagick \
        # docker-php-ext-enable imagick \
        # # Success
        # true \
        vim \
        wget \
        git \
        bzip2 \
        zip \
        libz-dev \
        libssl-dev \
        libnghttp2-dev \
        libpcre3-dev \
        libmemcached-dev \
        libzip-dev \
        libbz2-dev \
        libjpeg-dev \
        libpng-dev \
        curl \
        libcurl4-openssl-dev \
        libonig-dev \
        libxml2-dev \
        supervisor  \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        zlib1g-dev \
        # 221020 add libicu-dev g++ intl
        # libicu-dev g++ \
        # 221020 add libicu-dev g++ intl
        libmagickwand-dev \
    && docker-php-ext-configure intl \
    && docker-php-ext-install intl \
    # 如果安装的扩展需要自定义配置时,#    添加GD库相关的设置
    && docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ \
        # --with-gd 报错
        # --with-png=/usr 报错\
        # --with-xpm=/usr 报错\
        # --enable-gd-jis-conv \
        # 重新编译后,还是报错,后来又添加了一项
        ## --enable-gd-native-ttf #报错
    # 221020 add imagick-beta as imagick
    && pecl install imagick-beta \
    && echo "extension=imagick.so" > /usr/local/etc/php/conf.d/imagick.ini \
    && pecl clear-cache \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install zip \
    && docker-php-ext-install pdo_mysql \
    && docker-php-ext-install opcache \
    && docker-php-ext-install mysqli \
    && docker-php-ext-install mbstring \
    && docker-php-ext-install bz2 \
    && docker-php-ext-install soap \
    #    221020 add imagick
    # && docker-php-ext-install imagick  
    && rm -r /var/lib/apt/lists/*\
    && usermod -u 1000 www-data\
    && groupmod -g 1000 www-data    
# Composer安装
RUN curl -sS https://getcomposer.org/installer | php \
    && mv composer.phar /usr/local/bin/composer \
    && composer self-update --clean-backups
# Mysqli 扩展 自带 直接安装即可(当前数据库使用的mysqli查询的)
RUN docker-php-ext-install mysqli
# PDO 扩展 自带 直接安装即可
RUN docker-php-ext-install pdo_mysql
# Bcmath 扩展 自带 直接安装即可
RUN docker-php-ext-install bcmath
# Redis 扩展下载 pecl本地安装 开启扩展
RUN wget http://pecl.php.net/get/redis-${PHPREDIS_VERSION}.tgz -O /tmp/redis.tgz \
    && pecl install /tmp/redis.tgz \
    && rm -rf /tmp/redis.tgz \
    && docker-php-ext-enable redis
# memcached 扩展下载 pecl本地安装 开启扩展 前面已经通过 apt-get安装了libmemcached-dev依赖
RUN wget http://pecl.php.net/get/memcached-${MEMCACHED_VERSION}.tgz -O /tmp/memcached.tgz \
    && pecl install /tmp/memcached.tgz \
    && rm -rf /tmp/memcached.tgz \
    && docker-php-ext-enable memcached
# mongodb 扩展下载 pecl本地安装 开启扩展 前面已经通过
RUN wget http://pecl.php.net/get/mongodb-${MONGODB_VERSION}.tgz -O /tmp/mongodb.tgz \
    && pecl install /tmp/mongodb.tgz \
    && rm -rf /tmp/mongodb.tgz \
    && docker-php-ext-enable mongodb
# 开启php-fpm
# RUN php-fpm
CMD ["php-fpm", "-F"]

这里涉及traefik给nginx转发的问题,需要这么配置:
/var/lib/docker/volumes/dc1_lnmpnginxConf/_data/conf.d/default.conf

server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    location / {
        # root   /usr/share/nginx/html;
        root   /usr/share/nginx/html/weiyoun.com;
        index  index.html index.htm index.php;
        #伪静态
        if (!-e $request_filename)
        {
                rewrite (.*) /index.php;
        }
    }
    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    location ~ \.php$ {
        fastcgi_pass   php:9000;#这里php就是php容器的名字
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/html/weiyoun.com$fastcgi_script_name;#此处配置要注意,有坑
        include        fastcgi_params;
    }

traefik域名前后缀配置

http:
routers:
api:
entryPoints:
- "web"
rule: "Host(`traefik.pbeta.cn`)"
service: api@internal
whoami:
entryPoints:
- "web"
rule: "Host(`traefik.pbeta.cn`) && Path(`/whoami`)"
service: whoami@docker
ghost:
entryPoints:
- "web"
rule: "Host(`ghost.pbeta.cn`) "
service: ghost
services:
ghost:
loadBalancer:
servers:
- url: "http://47.74.154.202:2368/"