【概述】
- 简单docker搭建Ghost
- 复杂docker-compose搭建Ghost+Nginx
核心步骤
解析域名
启动docker容器
- 访问网页
具体步骤
- 域名:
购买服务器VPS+解析域名
- 环境:创建帐号,并预设权限
- 环境:安装docker和docker-compose
- 环境:
创建docker网络
,用于串联ghost和nginx等容器 - 博客:
配置ghost的映射目录和博客配置文件
- 博客:
创建运行ghost容器
- 代理:
配置nginx映射目录和代理配置文件
- 代理:
创建运行nginx容器
- 证书:
创建运行certbot容器,并更新证书
- 部署成果,访问成功
部署过程
购买服务器VPS+解析域名
- Linode注册充值(已弃用,改用oracle的)
官网:www.linode.com
推荐码:注册充值时,填写推荐码,可以获得20美金赠送。
推荐码:acd1469162f9392327ba6850077ea3512a521ec3
- Linode创建多个实例
- ping一番,考察下哪里的服务器快,保留快的那个实例,其它都可以删了
- 部署centos7系统,linode4669841_tokyo » Dashboard » Deploy an Image
- 在域名服务商那,修改dns记录,添加a记录指向你的服务器IP
创建帐号,并预设权限
- 创建ghost专用帐号
# 创建帐号
[opc@instance-20210526-1447 ~]$ sudo -i
[root@instance-20210526-1447 ~]# groupadd ghost
[root@instance-20210526-1447 ~]# useradd -m -g ghost ghost -c "Ghost Blog User"
[root@instance-20210526-1447 ~]# passwd ghost
Changing password for user ghost.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
[root@instance-20210526-1447 ~]# mkdir /www
[root@instance-20210526-1447 ~]# mkdir -p /www/ghost/content
[root@instance-20210526-1447 ~]# mkdir -p /www/nginx
[root@instance-20210526-1514 ~]# chown -R ghost /www
[root@instance-20210526-1447 ~]# ll /www | grep ghost
drwxr-xr-x. 3 ghost ghost 21 May 26 07:01 ghost
- 给ghost帐号增加一些权限
[root@instance-20210526-1447 ~]# visudo
#修改sudoers文件,
#使得用户ghost执行docker相关命令时,不需要密码
ghost ALL=/sbin/service,/bin/systemctl
ghost ALL=(ALL) NOPASSWD: /usr/bin/docker,/usr/bin/docker-compose,/usr/bin/yum,/bin/ln,/bin/snap,/bin/tar
[root@instance-20210526-1447 ~]# sudo su ghost
[ghost@instance-20210526-1447 root]$ cd ~
[ghost@instance-20210526-1447 ~]$ ls -a
. .. .bash_history .bash_logout .bash_profile .bashrc
[ghost@instance-20210526-1447 ~]$ vi .bashrc
alias docker="sudo /usr/bin/docker"
alias docker-compose="sudo /usr/bin/docker-compose"
alias apt-get="sudo /usr/bin/yum"
[ghost@instance-20210526-1447 ~]$ source ~/.bashrc
- ssh免密登录
[ghost@instance-20210526-1514 ~]$ mkdir .ssh
[ghost@instance-20210526-1514 ~]$ chmod 700 .ssh
[ghost@instance-20210526-1514 ~]$ sudo yum install -y lrzsz
# 上传xshell的pub公钥文件
[ghost@instance-20210526-1514 .ssh]$ rz
[ghost@instance-20210526-1514 ~]$ cd .ssh
[ghost@instance-20210526-1514 .ssh]$ touch authorized_key
[ghost@instance-20210526-1514 .ssh]$ cat oracle_20210526_rsa_2048.pub >> authorized_keys
[ghost@instance-20210526-1514 .ssh]$ chmod 600 authorized_keys
[ghost@instance-20210526-1514 .ssh]$ sudo systemctl restart sshd.service
- 防火墙改用iptables
[ghost@instance-20210526-1514 nginx]$ sudo su
[sudo] password for ghost:
[root@instance-20210526-1514 nginx]# systemctl stop firewalld
# 启用iptables管理 22,80,443
[root@instance-20210526-1514 nginx]# yum install -y iptables-services
[root@instance-20210526-1514 nginx]# systemctl start iptables
# 拷贝iptables备份文件覆盖/etc/sysconfig/iptables
[root@instance-20210526-1514 nginx]# vi /etc/sysconfig/iptables
[root@instance-20210526-1514 nginx]# cp /home/ghost/iptables /etc/sysconfig/iptables
cp: overwrite ‘/etc/sysconfig/iptables’? yes
[root@instance-20210526-1514 nginx]# systemctl restart iptables.service
安装docker和docker-compose
安装docker
[root@instance-20210526-1514 ~]# yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo # 使用官方源
[root@instance-20210526-1514 ~]# yum list docker-ce --showduplicates | sort -r # 查看可安装版本
* updates: ftp.iij.ad.jp
This system is not registered with an entitlement server. You can use subscription-manager to register.
: subscription-manager
Loading mirror speeds from cached hostfile
Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos,
* extras: ftp.iij.ad.jp
* epel: www.ftp.ne.jp
docker-ce.x86_64 3:26.1.4-1.el7 docker-ce-stable
...
* base: ftp-srv2.kddilabs.jp
Available Packages
[root@instance-20210526-1514 ~]# yum install docker-ce # 默认安装最新版
Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
Loading mirror speeds from cached hostfile
* base: ftp-srv2.kddilabs.jp
* epel: www.ftp.ne.jp
* extras: ftp.iij.ad.jp
* updates: ftp.iij.ad.jp
Resolving Dependencies
--> Running transaction check
---> Package docker-ce.x86_64 3:26.1.4-1.el7 will be installed
--> Processing Dependency: containerd.io >= 1.6.24 for package: 3:docker-ce-26.1.4-1.el7.x86_64
--> Processing Dependency: docker-ce-cli for package: 3:docker-ce-26.1.4-1.el7.x86_64
--> Processing Dependency: docker-ce-rootless-extras for package: 3:docker-ce-26.1.4-1.el7.x86_64
--> Running transaction check
---> Package containerd.io.x86_64 0:1.6.33-3.1.el7 will be installed
---> Package docker-ce-cli.x86_64 1:26.1.4-1.el7 will be installed
--> Processing Dependency: docker-buildx-plugin for package: 1:docker-ce-cli-26.1.4-1.el7.x86_64
--> Processing Dependency: docker-compose-plugin for package: 1:docker-ce-cli-26.1.4-1.el7.x86_64
---> Package docker-ce-rootless-extras.x86_64 0:26.1.4-1.el7 will be installed
--> Running transaction check
---> Package docker-buildx-plugin.x86_64 0:0.14.1-1.el7 will be installed
---> Package docker-compose-plugin.x86_64 0:2.27.1-1.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
==================================================================================================================================================================================
Package Arch Version Repository Size
==================================================================================================================================================================================
Installing:
docker-ce x86_64 3:26.1.4-1.el7 docker-ce-stable 27 M
Installing for dependencies:
containerd.io x86_64 1.6.33-3.1.el7 docker-ce-stable 35 M
docker-buildx-plugin x86_64 0.14.1-1.el7 docker-ce-stable 14 M
docker-ce-cli x86_64 1:26.1.4-1.el7 docker-ce-stable 15 M
docker-ce-rootless-extras x86_64 26.1.4-1.el7 docker-ce-stable 9.4 M
docker-compose-plugin x86_64 2.27.1-1.el7 docker-ce-stable 13 M
Transaction Summary
==================================================================================================================================================================================
Install 1 Package (+5 Dependent packages)
Total download size: 114 M
Installed size: 401 M
Is this ok [y/d/N]: y
Downloading packages:
warning: /var/cache/yum/x86_64/7/docker-ce-stable/packages/docker-buildx-plugin-0.14.1-1.el7.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY1 MB 00:00:20 ETA
Public key for docker-buildx-plugin-0.14.1-1.el7.x86_64.rpm is not installed
(1/6): docker-buildx-plugin-0.14.1-1.el7.x86_64.rpm | 14 MB 00:00:05
(2/6): containerd.io-1.6.33-3.1.el7.x86_64.rpm | 35 MB 00:00:11
(3/6): docker-ce-cli-26.1.4-1.el7.x86_64.rpm | 15 MB 00:00:03
(4/6): docker-ce-rootless-extras-26.1.4-1.el7.x86_64.rpm | 9.4 MB 00:00:01
(5/6): docker-compose-plugin-2.27.1-1.el7.x86_64.rpm | 13 MB 00:00:02
(6/6): docker-ce-26.1.4-1.el7.x86_64.rpm | 27 MB 00:00:14
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 5.7 MB/s | 114 MB 00:00:19
Retrieving key from https://download.docker.com/linux/centos/gpg
Importing GPG key 0x621E9F35:
Userid : "Docker Release (CE rpm) <docker@docker.com>"
Fingerprint: 060a 61c5 1b55 8a7f 742b 77aa c52f eb6b 621e 9f35
From : https://download.docker.com/linux/centos/gpg
Is this ok [y/N]: y
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : docker-buildx-plugin-0.14.1-1.el7.x86_64 1/6
Installing : containerd.io-1.6.33-3.1.el7.x86_64 2/6
Installing : docker-compose-plugin-2.27.1-1.el7.x86_64 3/6
Installing : 1:docker-ce-cli-26.1.4-1.el7.x86_64 4/6
Installing : docker-ce-rootless-extras-26.1.4-1.el7.x86_64 5/6
Installing : 3:docker-ce-26.1.4-1.el7.x86_64 6/6
Verifying : docker-compose-plugin-2.27.1-1.el7.x86_64 1/6
Verifying : containerd.io-1.6.33-3.1.el7.x86_64 2/6
Verifying : 3:docker-ce-26.1.4-1.el7.x86_64 3/6
Verifying : 1:docker-ce-cli-26.1.4-1.el7.x86_64 4/6
Verifying : docker-ce-rootless-extras-26.1.4-1.el7.x86_64 5/6
Verifying : docker-buildx-plugin-0.14.1-1.el7.x86_64 6/6
Installed:
docker-ce.x86_64 3:26.1.4-1.el7
Dependency Installed:
containerd.io.x86_64 0:1.6.33-3.1.el7 docker-buildx-plugin.x86_64 0:0.14.1-1.el7 docker-ce-cli.x86_64 1:26.1.4-1.el7 docker-ce-rootless-extras.x86_64 0:26.1.4-1.el7
docker-compose-plugin.x86_64 0:2.27.1-1.el7
Complete!
- 设置docker
[root@instance-20210526-1514 ~]# docker version # 查看更新后的版本
Client: Docker Engine - Community
Version: 26.1.4
API version: 1.45
Go version: go1.21.11
Git commit: 5650f9b
Built: Wed Jun 5 11:32:04 2024
OS/Arch: linux/amd64
Context: default
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
[root@instance-20210526-1514 ~]# systemctl start docker # 启动docker服务
[root@instance-20210526-1514 ~]# systemctl enable docker # 设置为开机服务
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@instance-20210526-1514 ~]# docker version
Client: Docker Engine - Community
Version: 26.1.4
API version: 1.45
Go version: go1.21.11
Git commit: 5650f9b
Built: Wed Jun 5 11:32:04 2024
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 26.1.4
API version: 1.45 (minimum version 1.24)
Go version: go1.21.11
Git commit: de5c9cf
Built: Wed Jun 5 11:31:02 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.33
GitCommit: d2d58213f83a351ca8f528a95fbd145f5654e957
runc:
Version: 1.1.12
GitCommit: v1.1.12-0-g51d5e94
docker-init:
Version: 0.19.0
GitCommit: de40ad0
- 安装docker-compose
[root@instance-20210526-1514 ~]# curl -L "https://github.com/docker/compose/releases/download/v2.18.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 52.0M 100 52.0M 0 0 6025k 0 0:00:08 0:00:08 --:--:-- 5873k
[root@instance-20210526-1514 ~]# sudo chmod +x /usr/bin/docker-compose
[ghost@instance-20210526-1514 certbot]$ docker-compose version
Docker Compose version v2.18.1
- 卸载清理docker
有可能你的服务器已经有docker和一些残留容器,需要手动清理
------------------卸载docker和docker-compose-----------------
[root@instance-20210526-1514 ~]# yum list installed | grep docker # 查看docker的本地版本
docker.x86_64 2:1.13.1-210.git7d71120.el7.centos @extras
docker-client.x86_64 2:1.13.1-210.git7d71120.el7.centos @extras
docker-common.x86_64 2:1.13.1-210.git7d71120.el7.centos @extras
docker-compose.noarch 1.18.0-4.el7 @epel
python36-docker.noarch 2.6.1-3.el7 @epel
python36-docker-pycreds.noarch 0.2.1-2.el7 @epel
python36-dockerpty.noarch 0.4.1-18.el7 @epel
[root@instance-20210526-1514 ~]# yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine docker-compose # 卸载
Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager
You need to be root to perform this command.
[ghost@instance-20210526-1514 certbot]$ sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
No Match for argument: docker-client-latest
No Match for argument: docker-latest
No Match for argument: docker-latest-logrotate
No Match for argument: docker-logrotate
No Match for argument: docker-engine
Resolving Dependencies
--> Running transaction check
---> Package docker.x86_64 2:1.13.1-210.git7d71120.el7.centos will be erased
---> Package docker-client.x86_64 2:1.13.1-210.git7d71120.el7.centos will be erased
---> Package docker-common.x86_64 2:1.13.1-210.git7d71120.el7.centos will be erased
--> Finished Dependency Resolution
Dependencies Resolved
===========================================================================================================================================================
Package Arch Version Repository Size
===========================================================================================================================================================
Removing:
docker x86_64 2:1.13.1-210.git7d71120.el7.centos @extras 64 M
docker-client x86_64 2:1.13.1-210.git7d71120.el7.centos @extras 13 M
docker-common x86_64 2:1.13.1-210.git7d71120.el7.centos @extras 4.4 k
Transaction Summary
===========================================================================================================================================================
Remove 3 Packages
Installed size: 76 M
Is this ok [y/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Erasing : 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 1/3
warning: /etc/sysconfig/docker-storage saved as /etc/sysconfig/docker-storage.rpmsave
Erasing : 2:docker-client-1.13.1-210.git7d71120.el7.centos.x86_64 2/3
Erasing : 2:docker-common-1.13.1-210.git7d71120.el7.centos.x86_64 3/3
Verifying : 2:docker-client-1.13.1-210.git7d71120.el7.centos.x86_64 1/3
Verifying : 2:docker-common-1.13.1-210.git7d71120.el7.centos.x86_64 2/3
Verifying : 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 3/3
Removed:
docker.x86_64 2:1.13.1-210.git7d71120.el7.centos docker-client.x86_64 2:1.13.1-210.git7d71120.el7.centos
docker-common.x86_64 2:1.13.1-210.git7d71120.el7.centos
Complete!
[root@instance-20210526-1514 ~]# docker version # 验证卸载成功
[root@instance-20210526-1514 ~]# yum remove docker-compose
[root@instance-20210526-1514 ~]# docker-compose version
------------------关闭docker实例-----------------
执行:docker-compose down停掉容器
报错:docker-compose down validating /www/certbot/docker-compose.yml: (root) Additional property certbot is not allowed
解决:这是旧版yml配置写法与新版docker-compose不兼容导致,根据 docker-compose 的标准,所有服务应该放在 services 下。
报错:docker-compose down validating /www/ghost/docker-compose.yml: services.ghost Additional property net is not allowed
解决:新版不支持net属性标签,改为networks,并且值为换行的- net_name
报错:docker-compose down service "ghost" refers to undefined network ghost_net: invalid compose project
解决:如果ghost_net已经存在,则需要定义一下服务节点“networks: ghost_net: external: true”
创建docker网络
[ghost@instance-20210526-1514 ~]$ docker network create ghost_net
6622eb06ad225655bf8b680a0de93825413ad8569b98d2ba0bc7cf60fb5b752b
[ghost@instance-20210526-1514 ghost]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
8dce76598c2e bridge bridge local
179cc6d32121 certbot_default bridge local
3ba098121ff5 ghost_net bridge local
67fca2971343 host host local
d837e32119cb none null local
配置ghost的映射目录和博客配置文件
- 宿主机目录将用于映射到容器里被读写,做到程序和数据分离
[ghost@instance-20210526-1514 ghost]$ mkdir -p data/var/lib/ghost/content
[ghost@instance-20210526-1514 ghost]$ mkdir -p data/var/lib/ghost/current/content
[ghost@instance-20210526-1514 ghost]$ cat data/var/lib/ghost/config.production.json # 这个文件可以在容器启动生成后修改
{
"url": "https://ghost.atibm.com/",
"server": {
"port": 2368,
"host": "0.0.0.0"
},
"database": {
"client": "sqlite3",
"connection": {
"filename": "/var/lib/ghost/content/data/ghost.db"
}
},
"logging": {
"transports": [
"file",
"stdout"
]
},
"process": "systemd",
"paths": {
"contentPath": "/var/lib/ghost/content"
}
}
创建运行ghost容器
- ghost镜像介绍
- https://hub.docker.com/_/ghost/
- 信息显示现在最新的版本有 1.19.0, 1.19, ..., latest
- 容器配置文件
[ghost@instance-20210526-1514 nginx]$ cat /www/ghost/docker-compose.yml
version: '3.8'
services:
ghost:
container_name: ghost
restart: unless-stopped
image: ghost:5.30.0 #4.24.0 # 4.5.0
#privileged: true
networks:
- ghost_net
volumes:
- /www/ghost/data/config.production.json:/var/lib/ghost/config.production.json
- /www/ghost/data/content:/var/lib/ghost/content
- /www/ghost/data/currentcontent:/var/lib/ghost/current/content
networks:
ghost_net:
external: true
- 启动ghost容器
[ghost@instance-20210526-1514 ghost]$ docker-compose up -d
[+] Building 0.0s (0/0)
[+] Running 1/1
✔ Container ghost Started 1.9s
[ghost@instance-20210526-1514 ghost]$ docker-compose logs
ghost | [2024-06-12 02:06:35] INFO Ghost is running in production...
ghost | [2024-06-12 02:06:35] INFO Your site is now available on https://ghost.atibm.com/
ghost | [2024-06-12 02:06:35] INFO Ctrl+C to shut down
ghost | [2024-06-12 02:06:35] INFO Ghost server started in 4.068s
ghost | [2024-06-12 02:06:37] INFO Database is in a ready state.
ghost | [2024-06-12 02:06:37] INFO Ghost database ready in 5.194s
配置nginx映射目录和代理配置文件
[ghost@instance-20210526-1514 ~]$ cd /www/nginx
[ghost@instance-20210526-1514 nginx]$ cat data/nginx.conf # 映射的nginx配置文件
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
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"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
[ghost@instance-20210526-1514 nginx]$ cat data/conf.d/default.conf # 映射的代理配置模板文件
server {
listen 80;
#server_name localhost;
server_name localhost nginx.atibm.com;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#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;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
# Let's encrypt
location ^~ /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}
location = /.well-known/acme-challenge/ {
return 404;
}
}
[ghost@instance-20210526-1514 nginx]$ cat data/conf.d/ghost.conf # 映射的ghost博客代理配置文件
# redirect all http traffic to https
server {
listen 80;
server_name ghost.atibm.com atibm.com www.atibm.com;
# google adsense ads.txt
location /ads.txt {
alias /usr/share/nginx/html/ghost/ads.txt;
}
return 301 https://$host$request_uri;
}
# redirect some domain https traffic to https://ghost.atibm.com
server {
listen 443 ssl;
server_name atibm.com www.atibm.com;
ssl_certificate /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ghost.atibm.com/privkey.pem;
location /ads.txt {
alias /usr/share/nginx/html/ads.txt;
}
return 301 https://ghost.atibm.com$request_uri;
}
# defined ghost.atibm.com 443
server {
listen 443 ssl;
server_name ghost.atibm.com;
ssl_certificate /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ghost.atibm.com/privkey.pem;
root /var/lib/ghost/current/core/server/public;
access_log /var/log/nginx/ghost-access.log main;
error_log /var/log/nginx/ghost-error.log warn;
location /ads.txt {
alias /usr/share/nginx/html/ghost/ads.txt;
}
location / {
proxy_pass http://ghost:2368;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffers 4 32k;
client_max_body_size 10m;
client_body_buffer_size 128;
}
}
创建运行nginx容器
容器配置文件
[ghost@instance-20210526-1514 nginx]$ cat /www/nginx/docker-compose.yml
version: '3.8'
services:
nginx:
container_name: "nginx"
image: nginx:1.21.0
restart: unless-stopped
#privileged: true
volumes:
- ./data/nginx.conf:/etc/nginx/nginx.conf
- ./data/conf.d:/etc/nginx/conf.d
- ./data/html:/usr/share/nginx/html
- ./data/logs:/var/log/nginx
- /www/certbot/data/letsencrypt:/etc/letsencrypt
networks: [ghost_net]
ports:
- "80:80"
- "443:443"
environment:
- NGINX_HOST=nginx.atibm.com
- NGINX_PORT=80
networks:
ghost_net:
external: true
- 启动nginx容器
[ghost@instance-20210526-1514 nginx]$ docker-compose up -d
[+] Building 0.0s (0/0)
[+] Running 1/1
✔ Container nginx Started
创建运行certbot容器,并更新证书
- 流程说明
用certbot docker -> 通过certbot certonly命令 -> 用邮箱向letsencrypt.org申请更新 -> 配合域名TXT验证记录 -> 获得证书文件 -> nginx配置读取证书文件 -> 访问https://ghost博客成功
[ghost@instance-20210526-1514 ~]$ cd /www/certbot/
# 容器配置文件
[ghost@instance-20210526-1514 certbot]$ cat /www/certbot/docker-compose.yml
version: '3.8'
services:
certbot:
container_name: "certbot"
image: certbot/certbot:v1.14.0
restart: unless-stopped
tty: true
stdin_open: true
volumes:
- ./data/letsencrypt:/etc/letsencrypt # 证书持久化
- ./data/backup:/var/lib/letsencrypt/backup
- ./data/cron-root:/etc/crontabs/root # 证书更新任务每周
- ./data/certbot-renew.log:/var/log/certbot-renew.log # 证书更新任务的执行日志
entrypoint: "/bin/sh" # 必须使用 entrypoint 而不是 command, 以重写 certbot image 的 entrypoint
# 创建运行certbot容器
[ghost@instance-20210526-1514 certbot]$ docker-compose up -d
# 进入容器
[ghost@instance-20210526-1514 certbot]$ docker-compose exec certbot sh
/opt/certbot #
# 查看证书有效期
/opt/certbot # certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: ghost.atibm.com
Serial Number: 336402f715a5e2e8d9a37e60f3ef22bebdc
Key Type: RSA
Domains: ghost.atibm.com
Expiry Date: 2021-08-25 04:34:08+00:00 (VALID: 29 days)
Certificate Path: /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/ghost.atibm.com/privkey.pem
Certificate Name: ghost.atibm.com
Serial Number: 4dc16882a468e352fe437d1e10c0bae5bf7
Key Type: RSA
Domains: ghost.atibm.com
Expiry Date: 2021-08-25 23:53:11+00:00 (VALID: 29 days)
Certificate Path: /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/ghost.atibm.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 更新你的域名证书
[ghost@instance-20210526-1514 certbot]$ docker-compose exec certbot sh
# 这句命令的效果是申请4个域名到一个证书里,按提示输入你的邮箱,能收件就行。
/opt/certbot # certbot certonly --cert-name ghost.atibm.com -d ghost.atibm.com -d atibm.com -d www.atibm.com -d trilium.atibm.com -d triliumcn.atibm.com --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory --manual
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): youraccount@mail.com
...
Account registered.
Requesting a certificate for ghost.atibm.com and 4 more domains
Performing the following challenges:
dns-01 challenge for atibm.com
dns-01 challenge for ghost.atibm.com
dns-01 challenge for trilium.atibm.com
dns-01 challenge for triliumcn.atibm.com
dns-01 challenge for www.atibm.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.atibm.com with the following value:
0j_CAdI8yxRO2yQRmm4pFeyz2bvqdQNJmb4Hc65nAII
Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
# 到这一步先别往下,停住,把这串编码,添加到你的域名txt记录里
# txt _acme-challenge.atibm.com 0j_CAdI8yxRO2yQRmm4pFeyz2bvqdQNJmb4Hc65nAII
# 如果登录域名管理后台也能完成操作,但我使用api token调用完成
# 再开一个新的VPS终端连接,进行操作
# 需要用到 dns-lexicon包,容器没销毁之前,安装一次就行
/opt/certbot # pip install dns-lexicon
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge --content 0j_CAdI8yxRO2yQRmm4pFeyz2bvqdQNJmb4Hc65nAII --auth-username 域名网站的登录帐号 --auth-token 这里是你域名商提供的api_token
# 如果添加成功,会显示以下信息
RESULT
---------
246028402
# 刚才那个证书申请界面,可以继续了,会提示成功如下
Cleaning up challenges
Subscribe to the EFF mailing list (email: xxx@xxx.xxx).
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/ghost.atibm.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/ghost.atibm.com/privkey.pem
Your certificate will expire on 2024-09-10. To obtain a new or
tweaked version of this certificate in the future, simply run
certbot again. To non-interactively renew *all* of your
certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
# dns记录销毁
/opt/certbot # lexicon namecom delete atibm.com TXT --name _acme-challenge --auth-username 域名网站的登录帐号 --auth-token 这里是你域名商提供的api_token
到这一步,nginx已经能访问证书文件,并且也能处理你的博客访问,需要刷新一下配置
/opt/certbot # exit #从certbot容器退出,回到宿主机
[ghost@instance-20210526-1514 certbot]$ docker exec nginx nginx -s reload
后续证书到期之前,会有邮件通知你,进certbot容器更新一下就行了
/opt/certbot # certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ghost.atibm.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificates are not due for renewal yet:
/etc/letsencrypt/live/ghost.atibm.com/fullchain.pem expires on 2024-09-10 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 定时任务更新证书 - 不支持manual模式,需要standalone或web模式,这个我没弄好
# 增加定时任务,每周尝试更新正式(前提是certbot已经定义了域名证书文件,renew才能有效,证书会在到期30天可以续订更新证书)
/opt/certbot # crontab -e
# do daily/weekly/monthly maintenance
# min hour day month weekday command
5 2 * * 0 certbot renew --quiet >> /var/log/certbot-renew.log 2>&1
# 手动更新证书 - 利用域名商的api接口,执行命令
--------同时开3个窗口 之 手动续期1/3 ----------
[ghost@instance-20210526-1514 certbot]$ docker-compose exec certbot sh
# 申请多个域名的新证书
/opt/certbot # certbot certonly --cert-name ghost.atibm.com -d ghost.atibm.com -d atibm.com -d www.atibm.com -d trilium.atibm.com -d test.atibm.com --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory --manual
# 扩展新域名证书
/opt/certbot # certbot certonly --cert-name ghost.atibm.com --expand -d ghost.atibm.com -d atibm.com -d www.atibm.com -d trilium.atibm.com -d test.atibm.com --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory --manual
...
Please deploy a DNS TXT record under the name
_acme-challenge.www.atibm.com with the following value:
dpZTUssWbUF9kg49W9RgHoZxAkm18G_WG_5Byws4ck8
...
-----dns记录销毁
/opt/certbot # lexicon namecom delete atibm.com TXT --name _acme-challenge --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.www --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.ghost --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.trilium --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.test --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.triliumcn --auth-username ATdoit --auth-token yourtoken;
-------- 同时开3个窗口 之 添加dns记录2/3 ----------
/opt/certbot # pip install dns-lexicon
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge --content sZOrBtQxdp4Mco33jG42F2Tzs4DK7bX5my-xiyITFTs --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.ghost --content EHreZqYRd2AtIWHFrbZ-lVwfIbtVjiIwKk9-nfW6QGw --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.trilium --content Z6CfrmTS47RW8EWKgqZzweIjq_Sgh4ehHKj06sM1jkQ --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.test --content t6R0lsjDpe9sBPFZ1kpMEx593dUozf2EwhTkX1cES4A --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.www --content _OWfZX5Z8f11TszICy2Ga2IdAKSCJuFsjJrRkgtzxTg --auth-username ATdoit --auth-token yourtoken
-------- 同时开3个窗口 之 nginx重载3/3 ----------
在certbot里确认,并提示通过后,到宿主机重载
[ghost@instance-20210526-1514 certbot]$ docker exec nginx nginx -s reload
部署完成,访问成功
- 博客地址:现在我们访问【ghost.atibm.com】
- IP解析:经过【域名 dns】解析到【服务器】
- 反向代理:由【服务器 nginx服务】做代理处理,访问内部网络【服务器 docker network:ghost_net】
- 博客服务:找到并访问【服务器 ghost服务】+【服务器 certbot服务生成的证书文件】,博客数据存储到【ghost容器映射宿主机目录】下,
- 经过一番折腾,我们实现了代理、程序、数据、证书全部分离,并一起工作,并且后续维护简单,比如升级ghost,备份数据等等。
备份:后续还要编写一键备份脚本,免费实现数据安全
扩展性:当然还可以体验别的网站程序,比如wiki、ss、leanote、trilium等
运维:有了vps挺爽的,可以随便玩,加上docker的易维护,不怕服务器搞坏
服务器:同时也可以在linode再次新增一个实例出来调试,不影响现有网站
linode已经闲置了,感谢支持