docker部署多网站

Wen 发布于 2023-05-17 780 次阅读


test

背景

只想把网站部署在docker上,也就是all in docker

说明

使用nginx进行不同域名转发到不同的docker容器项目;
docker的通信网上大多是通过映射端口到宿主机来实现,如果你没有宿主机与docker通信的需要,则没有需要这样做。
单单docker之间的通信的话,使用docker network(也即docker的子网)即可实现。
只要通信的两个docker加入了同一个docker的子网即可使用别名通信,
比如这样 http://docker1:80 其它的同子网的容器就可以这样访问到别名为docker1的容器。
宿主机的80和443端口则由nginx的docker容器统一管理,以下是我一个实际案例的过程。

docker compose

我这里使用docker compose来创建容器,使用命令也是可以的,创建容器时使用 --net 参数加入子网即可
以下是从docker compose官方示例抄来的wordpress示例

services:
  # 这个wpdb就是子网里的别名,如果你网络里有同名的建议修改
  wpdb:
    # We use a mariadb image which supports both amd64 & arm64 architecture
    image: mariadb:10.6.4-focal
    # If you really want to use MySQL, uncomment the following line
    #image: mysql:8.0.27
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=somewordpress
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=wordpress
    expose:
      - 3306
      - 33060
  wordpress:
    image: wordpress:latest
    volumes:
      - wp_data:/var/www/html
    depends_on:
      - wpdb
    # 这里暴露80端口是在子网里面暴露与nginx容器通信的,宿主机访问不到
    # 不添加也是可以的,wordpress容器默认暴露80端口,针对你使用的镜像自行选择是否加上
    expose:
      - 80
    restart: always
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=wordpress
      - WORDPRESS_DB_NAME=wordpress
  nginx:
    # 使用alpine的镜像,占用更小
    image: nginx:alpine
    # 映射端口:容器端口
    ports:
      - 443:443
      - 80:80
    # 依赖,以下容器必须先启动
    depends_on:
      - wordpress

# 这段作用是加入已有的子网,name写你已存在的子网名
networks:
  defalut:
    external: true
    name: default-network

volumes:
  db_data:
  wp_data:

由于我们是使用docker nginx来转发wordpress的请求,所以除了nginx其余不必映射到宿主机,nginx的配置可能不对,自己看需要改。

还有networks的配置,如果没有的话,docker compose会自动创建一个新的子网,以docker-compose.yml在的文件夹名后加_dafault 来命名的子网。

Nginx配置

下面就是重点,nginx的配置,我的建议是一项目一个配置文件,放在容器的/etc/nginx/conf.d/下,比如两个网站,就按域名作为文件名,分别两个配置文件

下面是一个有ssl的nginx示例

# one.example.com.conf
server {
    # https
    listen  443 ssl;
    listen  [::]:443 ssl;

    # 实际的域名
    server_name         one.example.com;

    # 证书 如果你使用记得修改成实际文件路径
    ssl_certificate     /etc/nginx/certs/one.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/one.example.com.key;

    location / {
        # 这里就是写上docker容器地址
        proxy_pass  http://wordpress:80;
        proxy_set_header      X-Real-IP remote_addr;
        proxy_set_header      X-Forwarded-Forproxy_add_x_forwarded_for;
        proxy_set_header      Host host; # 这个必须加上,没有的话,会自动跳转到wordpress-one地址
        proxy_set_header X-Forwarded-Protoscheme;
    }
}
server {
    listen 80;
    listen  [::]:80;
    server_name one.example.com;
    return 301 https://http_hostrequest_uri;
}

另一个地址的

# two.example.com.conf
server {
    # https
    listen  443 ssl;
    listen  [::]:443 ssl;

    # 实际的域名
    server_name         two.example.com;

    # 证书 如果你使用记得修改成实际文件路径
    ssl_certificate     /etc/nginx/certs/two.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/two.example.com.key;

    location / {
        # 这里就是写上docker容器地址
        # 由于只创建了一个wordpress,所以写了同样的地址做示例,
        proxy_pass  http://wordpress:80;
        proxy_set_header      X-Real-IP remote_addr;
        proxy_set_header      X-Forwarded-Forproxy_add_x_forwarded_for;
        proxy_set_header      Host host; # 这个必须加上,没有的话,会自动跳转到wordpress-one地址
        proxy_set_header X-Forwarded-Protoscheme;
    }
}
server {
    listen 80;
    listen  [::]:80;
    server_name two.example.com;
    return 301 https://http_hostrequest_uri;
}

这里说一下proxy_pass 的设置,里面的wordpress就是容器在子网里的别名,只要这个nginx容器和wordpress容器在一个子网里就能访问到,里面的proxy_set_header Host $host;则必须加上,不然会自动跳转到类似 http://子网名 这样的地址。

容器加入的子网可以使用docker inspect 容器ID查询,目前docker所有已创建的子网可以使用docker network list查询

按上面的nginx配置好后,如果你在两个nginx配置文件的proxy_pass写了不同的地址,那么访问one.example.com或者two.example.com就能访问到对应的容器

此作者没有提供个人介绍
最后更新于 2024-05-15