写下这篇主要是因为之前的教程已经有点过时了,centos7.8也没有维护了,docke新版本可能存在与系统不兼容的情况,所以这次更新为使用最新的docker和dockercompose,改用为Ubuntu系统。

准备

  • 一台初始化的Ubuntu系统(24.04 64位)
  • 一个备案好的域名
  • 一个cloudflare账号

服务器配置

修改SSH端口号

连接服务器:

1
ssh root@you ip

修改端口,编辑sshd_config文件:

1
vi /etc/ssh/sshd_config

输入 i 编辑,把#去掉,把22改为想要的端口,最后:wq保存:

1
Port 10024

用编辑器打开 /lib/systemd/system/ssh.socket 文件

1
sudo vim /lib/systemd/system/ssh.socket

ListenStream=22 中的 22 端口号修改为你刚才设置的端口号

1
ListenStream=10024

重启服务

1
2
3
sudo systemctl daemon-reload

sudo systemctl restart ssh.socket

免密登录

在本地电脑生成SSH Key,一直回车就可以:

1
ssh-keygen

在本地路径C:\Users\你的用户\.ssh下创建config文件:

1
2
3
4
5
6
Host Test
Port #端口号
HostName #IP地址
User root
IdentityFile #本地id_rsa文件
IdentitiesOnly yes

服务器cd ~/.ssh/目录,(一定要CD到这个目录,切勿直接在根目录直接使用下面命令,会导致这个文件不生效)编辑文件,到本地C:\Users\你的用户名\.ssh 找到公钥文件,把本地电脑的公钥文件id_rsa.pub复制进去,:wq保存:

1
vi authorized_keys

如果之前连接过服务器,格式化后再连接可能报错,可以先删除本地电脑这两个文件,这两个文件是历史连接的记录

至此,完成服务器的端口修改和使用密钥登录的操作

安装Docker和Compose插件

阿里云安装Docke文档:https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docke

安装:

执行以下命令安装Docker社区版本:

1
2
3
4
5
6
7
8
9
10
11
12
#更新包管理工具
sudo apt-get update
#添加Docker软件包源
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
sudo curl -fsSL http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository -y "deb [arch=$(dpkg --print-architecture)] http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
#安装Docker社区版本,容器运行时containerd.io,以及Docker构建和Compose插件
sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
#启动Docker
sudo systemctl start docker
#设置Docker守护进程在系统启动时自动启动
sudo systemctl enable docker

通过查看Docker版本命令,验证Docker是否安装成功。

1
sudo docker -v

配置镜像源:

  1. 注册登录cloudflare,选择Workers 和 Pages,这两个部署方式都是可以的;
  2. Pages方式:连接github仓库,选择github仓库(Fork过来的开源仓库),直接开始默认设置就可以
  3. Workers :复制 _worker.js 代码,保存并部署即可
  4. 修改文件 /etc/docker/daemon.json(如果不存在则创建)
1
2
3
4
5
6
7
8
9
10
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://docker.fxxk.dedyn.io"] # 请替换为您自己的Worker自定义域名
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

安装acme&生成证书

安装acme

acme官网Githubhttps://github.com/acmesh-official/acme.sh

安装:(这里一定要带上自己的邮箱,否则后面会报错,会有记录报错,需要多试几次)

1
curl https://get.acme.sh | sh -s email="[email protected]"

这个命令安装acme并且创建了一个 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书.

注意:安装好之后建议重新连接服务期,如果这个时候直接使用acme.sh可能有问题

生成证书

DNS APi的安装方式:https://github.com/acmesh-official/acme.sh/wiki/dnsapi

以下是cloudflare的生成证书方式:

1
2
3
export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export CF_Email="[email protected]"
acme.sh --issue --dns dns_cf -d domain.com -d *.domain.com

安装Nginx容器

流程梳理

  1. 创建home/keys文件夹,存放Https证书文件
  2. 创建随机的密钥
  3. 创建容器的局域网段https
  4. 创建/home/keys/nginx/conf.d文件夹,存放nginx的配置文件
  5. 创建nginx.conf文件,并上传到服务器home/nginx文件夹下
  6. 通过docker-cpmpose文件安装Nginx
  7. 最后执行acme.sh命令

Tip:把所有的配置文件都放在home文件夹下,方便以后管理,目录使用英文并具有一定意义

Https文件存放

按照上面的流程,我们需要把https证书放到一个可以让nginx容器访问到的地方,这是一个官方的示例:

1
2
3
4
acme.sh --install-cert -d example.top \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"

(一个小提醒, 这里用的是 service nginx force-reload, 不是 service nginx reload, 据测试, reload 并不会重新加载证书, 所以用的 force-reload)

因为我们使用的是Docker的方式安装Nginx,所以我们需要修改一下,把目录都放到home目录的key文件夹下(记得域名改为自己的)

创建文件夹:mkdir /home/keys,存放Https证书文件,这一步只需要创建文件夹,无需执行命令,最后再执行。

1
2
3
4
acme.sh --install-cert -d example.top \
--key-file /home/keys/key.pem \
--fullchain-file /home/keys/cert.pem \
--reloadcmd "docker restart some-nginx"

这句命令主要为域名创建了两个证书文件,并放在key指定文件夹下,最后重启some-nginx容器

创建随机的密钥

  • 创建随机的https证书密钥:

    1
    openssl dhparam -out /home/keys/dhparam.pem 2048

创建容器的局域网段

创建容器的局域网段https:

1
2
3
4
5
6
# 创建容器的局域网段https
docker network create https
#这是查询network有哪些网段
docker network ls
#这是查询network里面https网段里面有哪些容器加入进来
docker network inspect https

nginx的配置文件存放

  • 创建文件夹:

    1
    2
    mkdir /home/nginx
    mkdir /home/nginx/conf.d

创建nginx.conf文件

  • 创建nginx.conf文件,并上传到服务器home/nginx文件夹下,这是一个通用的文件配置

    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    user nginx;
    worker_processes auto;
    pid /run/nginx.pid;
    worker_rlimit_nofile 65535;
    events {
    # 设置事件驱动模型,是内核2.6以上支持
    use epoll;
    worker_connections 65535;
    accept_mutex off;
    multi_accept off;
    }

    http {
    # Basic Settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    send_timeout 120;
    keepalive_timeout 300;
    client_body_timeout 300;
    client_header_timeout 120;

    proxy_read_timeout 300;
    proxy_send_timeout 300;
    #tcp_nopush on;
    types_hash_max_size 4096;
    client_header_buffer_size 16m;
    client_max_body_size 4096m;

    include /etc/nginx/mime.types;
    include /etc/nginx/conf.d/*.conf;
    # include /usr/share/nginx/modules/*.conf;

    default_type application/octet-stream;
    # Logging Settings
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';
    # 开启gzip
    gzip on;
    # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
    gzip_min_length 1k;
    # gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
    gzip_comp_level 2;
    # 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;
    # 禁用IE 6 gzip
    gzip_disable "MSIE [1-6]\.";
    }

安装Nginx

  • 接下来是Nginx容器安装,编写docker-compose文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
services:
web:
image: nginx:latest
container_name: "some-nginx"
restart: always
volumes:
- /home/nginx/nginx.conf:/etc/nginx/nginx.conf
- /home/nginx/conf.d:/etc/nginx/conf.d
- /home/keys:/home/keys
# blog
- /home/blog:/var/www
ports:
- "80:80"
- "443:443"

# docker network create https
networks:
https:
external: true

解释:创建了一个some-nginx的容器,把容器文件nginx.confconf.d和keys文件夹挂载出来。暴露端口是80和443;把容器加入到https的网段里面,让这个网段里面的容器可以被nginx容器代理到。

编写好后就可以直接使用一下命令安装:

1
docker compose up -d

执行acme.sh命令

最后我们就可以运行之前acem的安装命令:

1
2
3
4
acme.sh --install-cert -d example.top \
--key-file /home/keys/key.pem \
--fullchain-file /home/keys/cert.pem \
--reloadcmd "docker resatrt some-nginx"

正常的话,这里运行着一个nginx容器了,这里的步骤稍微复杂但是细心一点还是没有难度的,特别需要注意的是域名、文件夹和文件名这些内容不要写错。

截止到这里,基本已经完成基本的架构,只需要其他docker容器加入到https这个网段内,通过conf文件,让nginx这个容器可以访问到就可以了。

最佳实践

可能用到的工具

可能用到的指令

一些踩过的坑