如何用Docker优雅地管理你的Nginx

如果你只有一台服务器,并且有多个服务需要NGINX代理提供服务,还想使用Docker服务跑你的NGINX服务器,那么你就应该单独管理你的NGINX服务容器,而不应该在其它应用部署时强耦合到项目下的docker-compose.yaml进行相应的部署,那应该如何优雅的管理你的NGINX服务呢? 那既然你能看到这篇博文,相信它必定对你管理NGINX服务容器有一定的启发~

单独建立一个Docker下的NGINX管理项目

例如你可以建立一个如下目录结构的项目,项目名称随意,如docker-nginx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ tree
.
├── config                    // 配置目录
│   ├── Dockerfile            // Dockerfile
│   ├── nginx.conf            // NGINX配置文件
│   ├── ca                    // SSL证书目录
│   │   ├── api.wumoxi.com
│   │   │   ├── cert.key
│   │   │   └── cert.pem
│   │   └── wumoxi.com
│   │       ├── cert.key
│   │       └── cert.pem
│   └── ss                    // 服务(或者说虚拟主机)配置目录
│       ├── api.wumoxi.com.conf
│       └── wumoxi.com.conf
└── docker-compose.yaml       // 容器管理工具配置文件

在这个项目目录下有一个docker-compose.yaml文件和一个config目录。来看一下主要的Docker相关的配置文件config/Dockerfiledocker-compose.yaml 的具体内容及NGINX配置文件。

config/Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
FROM yobasystems/alpine-nginx

# 拷贝证书和虚拟主机配置文件以及NGINX配置文件到容器环境内部.
COPY ca /etc/nginx/ca
COPY ss /etc/nginx/ss
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露容器服务端口号(注意这里暴露了80和443,如果你配置域名的SSL暴露这个端口号是必须的).
EXPOSE 80
EXPOSE 443

注意这里使用了yobasystems/alpine-nginx这个镜像。

docker-compose.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
version: "3.6"

# docker composer 管理的服务
services:
  # nginx-server 是容器服务名称,例如:容器如与容器之间访问服务的话,
  # 需要指定这个服务名称,稍后讲一下config/ss/api.wumoxi.com.conf这个文件的时候你自然会明白。
  nginx-server:
    # 指定这个nginx-server服务运行所在容器的名称。
    container_name: nginx_server
    # 指定要构建镜像所使用的Dockerfile文件所在目录,
    # 构建出来的镜像名称会以 [项目名称_容器服务名称] 的形式存在,
    # 如该项目构建出来的镜像将会是 `dockernginx_nginx-server` 名称的镜像存在。
    build: './config'
    # 将Dockerfile指定的容器暴露端口号与宿主主机关联。
    # 注意端口关联是以,[宿主主机端口号:容器暴露端口号] 的形式存在的,
    # 那你如果是刚开始接触Docker可能分不清,这里一定要明确哪个是宿主主机端口哪个是容器暴露端口。
    # 可以有多个,这个要根据容器向外暴露的具体端口而定。
    ports:
      - '80:80'
      - '443:443'
    # 指定容器的重启方式,可选值为["no", always, on-failure, unless-stopped]
    restart: always
    # 指定容器是不是对挂载目录有写入权限
    privileged: true
    # 挂载宿主主机目录到容器,可以有多个,当然你也可以用容器数据卷进行挂载
    volumes:
      - /usr/local/data/docker/nginx/www:/etc/nginx/html
    # 容器所使用的网络
    networks:
      - default
      - externals

# 网络定义,这个地方定义了一个名称为[externals]网络的外部网络
# 注意:让需要链接的容器同属一个外部网络,那现在这个nginx-server容器服务就在这个名称为 [externals] 的外部网络中。
# 那你要在这个NGINX容器服务中代理其它容器服务,例如有一个 [gin-app] 的容器服务,那么它们两个必须属于同一个网络。
networks:
  externals:
    external: true

要让nginx-server与gin-app这两个容器服务使用同一个外部网络externals,因此,需要在启动这两个容器之前通过以下命令创建外部网络:

1
$ docker network create externals

config/nginx.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# run nginx in foreground
daemon off;

#user nobody;

worker_processes 1;

error_log  stderr error;
error_log  stderr notice;
error_log  stderr info;

events {
    worker_connections 1024;
}

http {
    # Include mime types.
    include mime.types;

    # Default content type.
    default_type  application/octet-stream;

    # Save access log to file.
    access_log /dev/stdout;

    # Hide NGINX server version. Ref: https://www.tecmint.com/hide-nginx-server-version-in-linux/
    server_tokens off;

    # Auto send static file to browser. Ref: https://www.jianshu.com/p/70e1c396c320?utm_campaign
    sendfile on;

    # The first parameter sets a timeout during which a keep-alive client connection will stay open on the server side.
    # The zero value disables keep-alive client connections.
    keepalive_timeout  65;

    # Open gzip transfer.
    gzip on;

    # Include multipart server config files.
    include ./ss/*.conf;
}

可以在这个文件的最后一行看到它会引入config/ss目录下的所有以.conf为后缀的虚拟主机配置文件。那具体到每一个虚拟主机是怎么代理容器服务的呢?下面以二级域名api.wumoxi.com的虚拟主机配置config/ss/api.wumoxi.com.conf 为例说明一下怎么代码容器服务。

代理容器服务

如现有一个Golang项目并且其项目目录下定义了docker-compose.yaml文件如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
version: "3.6"
services:
  gin-app:
    container_name: wumoxi.com.server
    build: "."
    ports:
      - '8859:8859'
    restart: always
    networks:
      - externals

networks:
  externals:
    external: true

虚拟主机config/ss/api.wumoxi.com.conf`配置文件具体内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
server {
    listen 443 ssl;
    server_name api.wumoxi.com;

    # SSL signature.
    ssl_certificate /etc/nginx/ca/api.wumoxi.com/cert.pem;
    ssl_certificate_key /etc/nginx/ca/api.wumoxi.com/cert.key;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 5m;

    # Http response body max size.
    client_max_body_size 8m;

    # Proxy application backend api service.
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 代理Golang项目,指定其host为容器服务名称[gin-app]加上服务端口号8859
        proxy_pass http://gin-app:8859/;
    }

    location ~ /\.ht {
        deny all;
    }
}

server {
    listen 80;
    server_name api.wumoxi.com;
    rewrite ^(.*) https://$host$1 permanent;
}

在NGINX容器环境内代理服务,指定的服务host是通过服务名称指定的,这个一定要明确。还有就是这两个容器服务必须是在同一外部网络下,nginx-server和gin-app就是在同一外部网络externals所以可以链接成功。以完成容器与容器间的数据传输。

使用NGINX容器服务

构建docker compose容器服务镜像

1
$ docker-compose build

运行docker compose容器服务

1
$ docker-compose up -d

停止docker compose容器服务

1
$ docker-compose down

本地测试线上使用

你在本地可以使用NGINX配置,待符合你的欲期的时候将项目上传到服务器你可以通过rsync,也可以版本库的方式。视具体情况而定。

comments powered by Disqus