利用 docker 部署 solo 并升级为 https

本贴最后更新于 2039 天前,其中的信息可能已经时移俗易

前言

这篇文章的内容在大概 2 周前就已经完成了,但是因为个人懒惰,所以一直没有进行总结和更新记录,大大的罪过啊,今天怎么也要开始重新梳理笔记了,接下来进入正题吧!

之前的博文:https://www.hicode.club/articles/2019/04/26/1556265891647.html 记录了安装博客系统 solo 的过程,但是美中不足的是当时使用的是 http,没能用上 https,后面在学习和实践过程中,将个人博客地址:www.hicode.club 改成了 https,这里记录下其中的关键点。

本篇文章会包含前作的内容,所以前作你可以不看,将这篇文章作为 solohttps 的参考文章,仅供参考!


最近好好学习了 Docker,所以想把线上环境的所有组件替换为 Docker 部署,对于 Solo 这个个人博客系统,至少需要部署 3 个 Docker 容器。

  1. MySQL
  2. Solo
  3. Nginx

其顺序也是从上倒下依次部署最为妥当,Docker 部署简单,对初学者而言难其中一个难点就是网络通信,我这里就把各个过程做一个记录。

准备工作

因为部署了 3 个 docker 容器,那么他们要互相访问,就不能(更准确来讲"不应该")通过传统的 localhost 或者 127.0.0.1 了。

官方也不再建议使用 --link 了,那么使用什么了?

官方推荐的是建立一个 docker 的网络,代码如下所示,其中 hicode 是我定义的网络名,大家可以改成自己喜欢的:

docker network create -d bridge hicode

后续每一个容器在建立的时候,都应该加入这个网络 hicode,然后容器和容器之间就可以通过容器名进行访问了。

MySQL

讲真,这个东西是最浪费时间。在 Docker 化之前,我服务器上用的是 MySQL8,当时就折腾了不少时间,虽然最终也部署起来了,但是后面考虑了下还是放弃了 8 这个版本,原因主要是如下几点:

  • MySql8 的资料相对较少,记录的问题解决方案也比较少,要爬坑很久才能找到解决方案。
  • MySQL8 的内存占用和 CPU 占用有点高,特别是内存占用持续高涨。我的云服务器是捋的腾讯羊毛,当时本来是 1核2G 的配置,我为了延长使用时间,把服务器配置降级成了 1核1G 了,所以对于 MySql8 的内存占用,我的小服务器有点扛不住。
  • 在可以预期的未来,我们公司包括整个行业还是会在 5.X 居多,所以 8.0 就留在后面有机会折腾了吧。

部署 MySQL 5.X 版本的指令如下所示

docker run --name mysql5.7 -p 3306:3306  \
--network hicode --privileged=true --restart=always \
-v /lcf/docker-data/mysql5.7/data:/var/lib/mysql \
-v /lcf/docker-data/mysql5.7/conf:/etc/mysql/conf.d \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=yourpwd -d mysql:5.7.26 \
--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci \
--lower_case_table_names=1 --default-time_zone='+8:00' 

上述命令还是有几个细节的,如下所示:

  • --network hicode 是加入之前我们新建的桥接网络 hicode
  • --privileged=true 是保证 MySQL 具有操作外部映射出的文件的权限
  • --restart=always 是自动启动,类似 Win 的自动重启
  • -v /lcf/docker-data/mysql5.7/data:/var/lib/mysql \ 将 mysql 的数据映射到磁盘上,避免新建容器后数据丢失。
  • -v /lcf/docker-data/mysql5.7/conf:/etc/mysql/conf.d 将 mysql 的配置放置在外部磁盘,方便修改
  • -e TZ=Asia/Shanghai 指定 mysql 的时区为 东八区,也就是我们中国时间
  • -e MYSQL_ROOT_PASSWORD=yourpwd 是需要你自己设置的密码

对于 mysql 的配置文件,因为我们映射到了外部,所以 mysq l 没有自动创建。如果在不映射外部的情况下,去看看 mysql 的内部配置文件,你会发现 mysql 官方帮我们定义了 3 个配置文件

  • docker.cnf 专门为 docker 做的优化
  • mysqldump.cnf dump 的时候做的优化
  • mysql.cnf 需要你自己定义

当然为了方便我们不需要这么麻烦,我们就合二为一创建一个 mysql.cnf 就够了,命令如下:

cd /lcf/docker-data/mysql5.7/conf
touch mysql.cnf

然后在 mysql.cnf 添加如下内容(其实这部你省略也是没有问题的)

[mysql]
# 以下是docker.cnf的内容
skip-host-cache
skip-name-resolve
# 以下是mysqldump.cnf的内容
quick
quote-names
max_allowed_packet  = 16M
# 以下内容如有需要请自己添加

然后重启 mysql 就行了

docker restart mysql5.7

=============以下步骤 Docker 安装的 MySQL 应该是不需要的,默认都可以访问=========
如果你需要指定 mysql 所有 ip 都访问

docker exec -it mysql5.7 /bin/bash
mysql -h 127.0.0.1 -u root -p 
# 此时要求你输入MySQL密码

# 此处特别注意了,需要你替换'yourpwd'为你的密码
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'yourpwd' WITH GRANT OPTION;
FLUSH PRIVILEGES;

=============以上步骤不需要,默认都可以访问=========

solo

solo 的安装注意 2 个细节即可,我们先看命令:

docker run -d  --restart=always --name solo \
    --network hicode\
    --env RUNTIME_DB="MYSQL" \
    --env JDBC_USERNAME="root" \
    --env JDBC_PASSWORD="yourpwd" \
    --env JDBC_DRIVER="com.mysql.jdbc.Driver" \
    --env JDBC_URL="jdbc:mysql://mysql5.7:3306/solo?useUnicode=yes&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC" \
    b3log/solo --listen_port=8080 --server_scheme=https --server_host=www.hicode.club

细节部分请注意了:

  • --network=hicode 加入 hicode 这个网络
  • --env JDBC_DRIVER="com.mysql.jdbc.Driver" 因为我使用的是 MySQL 5.7 所以是这样的
  • --env JDBC_PASSWORD="yourpwd" 是安装 myql 时候时候指定的密码
  • --server_host=www.hicode.club 需要你自己修改 host
  • --env JDBC_URL="jdbc:mysql://mysql5.7:3306/ 这个地方我写的不是 localhost 也不是 127.0.0.1,而是使用的 mysql 容器的名称 mysql5.7
  • --server_scheme=https 如果要通过 https 访问,那么此处必须是 https

Nginx

证书申请

https 相对比 http,最核心的一个东西就是证书,证书有免费的也有收费的,我这里介绍下几个免费获取的途径

腾讯云

免费渠道:https://buy.cloud.tencent.com/ssl?fromSource=ssl

image.png

请注意选择 域名免费版DV.

然后根据自己的情况进行资料填写。

image.png

接下来就是验证 域名归属,只有验证成功后才会给你颁发证书。

image-20190523213951118

如上所示,认证办法通常有 2 类

  • 修改 DNS 记录:推荐使用,在 DNS 提供商(腾讯云、阿里云等)的解析中添加一条 txt 的值。
  • 文件验证:省略

确定申请后,会出现如下图

image.png

那么在添加 txt 记录的时候,主机记录和记录值分别做上述添加即可。

具体的流程可以参考:

阿里云

免费渠道:https://common-buy.aliyun.com/?spm=5176.7968328.1266638..5e971232kiO2Lf&commodityCode=cas#/buy

image.png

FreeSSL

免费渠道:https://freessl.cn/

视频教程:https://blog.freessl.cn/how-to-use-freessl-issue-free-certificates/

关于证书的 100 问:https://blog.freessl.cn/freessl-org-frequently-asked-questions/

同时这个网站有大量通俗易懂的文章,推荐新手看看。

其他

https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E

证书下载

当验证了域名归属后,对应的机构就会给你颁发证书了,不同的 HTTP 服务器,需要不同的证书类型,下面是我在腾讯云申请的证书,默认提供了 4 类。

image.png

因为我用的是 Nginx,所以记录如下:

  • xxx.key 就是你的私钥文件,不要泄漏给别人哦。
  • xxx.crt 是你的证书文件

配置 Nginx

在证书下载下来后,接下来就是配置证书和反向代理了。

首先创建 nginx 的配置文件 nginx.conf

cd /lcf/docker-data/nginx/conf
touch nginx.conf

接下来请把 2 个证书相关的文件移动到 nginx.conf 的同级目录,然后进行如下配置。

worker_processes 1;
events {
    worker_connections 1024;
}
http {
    include mime.types;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    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" "$request_body"';
    access_log /var/log/nginx/logs/access.log  main;
    sendfile on;
    #开启gzip压缩
    gzip on;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_min_length 256k;
    gzip_types text/plain application/javascript text/css application/json application/x-javascript text/xml application/xml text/javascript;
    
    #后端的服务器
    upstream backend {
        server solo:8080 max_fails=3 fail_timeout=30s;
    }
    
    #个人博客
    server {
        # 最新写法,ssl on 的写法已经不推荐了!
        listen 443 ssl;
        server_name hicode.club www.hicode.club;
      	# 证书相关,https新增
        ssl_certificate hicode.club_bundle.crt;
        ssl_certificate_key hicode.club.key;
        ssl_session_timeout 5m;

        access_log /var/log/nginx/logs/hicode/access.log  main;
        location / {
            proxy_pass http://backend$request_uri;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header http_x_forwarded_for $remote_addr;
            client_max_body_size 10m;
        }
    }
    server {
        # http跳转到https,这样就只存在http的博客了
        listen 80;
        server_name hicode.club www.hicode.club;
        rewrite ^(.*)$	https://$host$1	permanent;
    }
}

上述内容中有 2 个 server

  • 第一个是 https 的配置,关键是其中证书的配置。
  • 第二是 http 跳转到 https 的配置。

安装 Nginx

然后执行如下命令启动 nginx 的容器

docker run -p 80:80 -p 443:443 -m 200m --restart always \
 --name nginx --network hicode \
 -v /lcf/docker-data/nginx/www:/www \
 -v /lcf/docker-data/nginx/conf/:/etc/nginx/ \
 -v /lcf/docker-data/nginx/logs:/var/log/nginx/logs \
 -v /lcf/docker-data/nginx/wwwlogs:/wwwlogs \
 nginx
  • 相比于单纯的 http,多一个 443 的端口映射。

其他

基本上,按照上面操作,就可以搞定了,docker 用好了,很方便,因为一行指令搞定的时候,不需要再折腾环境了。

有朋友担心资源占用的问题,这里我截图,给大家看看情况:

image.png

好了,差不多写到这里,有问题,欢迎留言。

最后归纳下同 http 部署方式的不同:

  • 申请证书
  • solo 指定为 https
  • nginx 多映射一个 443 端口

文章发布自:hicode.club,转载请注明出处,谢谢!

  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    492 引用 • 926 回帖
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1435 引用 • 10056 回帖 • 489 关注
  • HTTPS
    99 引用 • 274 回帖 • 3 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • vinasis 1 评论

    为啥不部署在一个 doctor 里

    Docker 是进程容器,一个进程对应一个容器。
    88250
  • jackfruitran

    我的 solo 版本还在 2.6 真想重新升级,奈何服务器是米国的,输入命令延迟也高,也懒得整。
    问楼主个问题,如果我想变成 https 需要证书 国内免费的需要备案吗,我之前备过案 但是迁移到国外了 就取消了,可以申请到吗,然后那台服务还搭的 ss,会影响吗

    1 回复
  • CodingOX
    1. 申请证书应该不需要备案的
    2. SS 没测试过,最多被 GFW 不能访问吧,如果没有,应该还是可用的
  • EuthL

    求助,在 nginx 的配置文件与楼主相同,但是返回了这个错误,实在解决不了了。
    2019/06/22 19:22:42 [emerg] 1#1: host not found in upstream "solo:8080" in /etc/nginx/nginx.conf:39
    nginx: [emerg] host not found in upstream "solo:8080" in /etc/nginx/nginx.conf:39

  • Nick1407

    谢谢大佬

  • someone
    作者

    上了容器了,最好一个萝卜一个坑!

  • someone

    你好, 有点没懂
    solo docker 里面是只有 solo 吗? 没有 nginx?
    solo 和 nginx docker 之间 只用 你说的 docker 网络连接?

    举一反三一下。。最近在看 ariang,是不是 aria2 或者 ariang(或者其他网页服务) 可以和 nginx 分为两个 docker 来用? 但是想想怎么连接呢?

    1 回复
  • CodingOX

    容器最好是一个萝卜一个坑,尽量轻量级,所以 solo 容器和 nginx 容器是 2 个东西!
    容器之间的网络通信,文章所描述的,应该是最好的方式了。
    第三个问题,还是那句话,应该保持容器轻量级!

  • 就 solo 放容器跑 就行了

    1 回复
  • CodingOX

    按照你的想法,还不如不放容器跑。。。

请输入回帖内容 ...