之前一直用的是宝塔面板来管理服务器,很多傻瓜化的一键操作,确实省心省事。但是这东西,用起来虽然方便,但是使用频率极低,一年半载下来,用不到几次。如果不关注相关的行业资讯,出了漏洞都不见得能够立即知道,发现的时候说不定为时已晚。

趁着这段时间不忙,可以重装一下服务器,改成 Docker 容器化部署应用。

Docker 容器

这个可以参考菜鸟教程,不同的操作系统(如CentOSUbuntuDebain等)安装也都差不多,跟着教程一步一步的走。

Nginx

建议先去 Docker Hub 中找到最新的 Nginx 版本,如nginx:1.25

Nginx 稍微麻烦一点,首先需要启动一个 Nginx,让其在容器内部生成配置文件。然后将配置文件复制出来,再关闭删除。

# 运行不带参数的 nginx
docker run --name nginx -d nginx:1.25
# 讲 nginx 容器内的配置文件复制到执行目录
docker cp nginx:/etc/nginx/nginx.conf /usr/local/docker/nginx
# 停止 nginx 容器
docker stop nginx
# 删除 nginx 容器
docker rm nginx

配置文件复制出来后,再执行带配置参数的运行命令。

docker run --name nginx --restart=always -p 80:80 -p 443:443 \
-v /etc/localtime:/etc/localtime \
-v /usr/local/docker/nginx/blog:/www \
-v /usr/local/docker/nginx/html:/usr/share/nginx/html \
-v /usr/local/docker/nginx/ssl:/etc/nginx/ssl \
-v /usr/local/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /usr/local/docker/nginx/logs:/var/log/nginx \
-d nginx:1.25
  • --name容器名称(下面不在复述)
  • --restart=always开机自启动,失败的一直尝试重启(下面不在复述)
  • -p 80:80 -p 443:443映射 80 和 443 端口(下面不在复述)
  • -v /etc/localtime:/etc/localtime与宿主机时间同步(下面不在复述)
  • -v /usr/local/docker/nginx/blog:/www存放博客的路径
  • -v /usr/local/docker/nginx/html:/usr/share/nginx/html存放其他资源的路径,没有可以去掉
  • -v /usr/local/docker/nginx/ssl:/etc/nginx/sslSSL证书文件路径
  • -v /usr/local/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.confNginx配置文件
  • -v /usr/local/docker/nginx/logs:/var/log/nginx日志文件,不需要可以去掉

PHP

建议先去 Docker Hub 中找到最新的 PHP 版本,如php:7.4-fpm

docker run --name php-fpm --restart=always -p 9000:9000 -v /etc/localtime:/etc/localtime -v /usr/local/docker/nginx/www:/www -d php:7.4-fpm
  • -v /usr/local/docker/nginx/blog:/www与 Nginx 的配置路径要一致

由于 Typecho 需要用到pdo_mysql的扩展,所需需要在容器中安装上扩展。

# 进入容器内部
docker exec -it php-fpm /bin/bash
# 安装 pdo_mysql 扩展
docker-php-ext-install pdo_mysql
# 安装 pcntl 扩展,因为我的 Say 插件需要用到 pcntl_fork 函数
docker-php-ext-install pcntl
# 查看是否安装成功
php -m
# 退出容器
exit

MySQL

建议先去 Docker Hub 中找到最新的 MySQL 版本,如mysql:5.7

docker run --name mysql --restart=always -p 3306:3306 -v /etc/localtime:/etc/localtime -v /usr/local/docker/mysql/conf:/etc/mysql/conf.d -v /usr/local/docker/mysql/logs:/var/log -v /usr/local/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7
  • -v /usr/local/docker/mysql/data:/var/lib/mysql数据存储路径
  • -e MYSQL_ROOT_PASSWORD=password记得修改 ROOT 密码

Bridge 网络

现在三个容器都是相互独立的,我们需要把它们组合在一个网络中。

# 创建一个自定义的 Bridge 网络
docker network create typecho
# 将容器加入到新建的网络
docker network connect typecho nginx
docker network connect typecho php-fpm
docker network connect typecho mysql
# 查看网络情况
docker network inspect typecho

可以看到新建的网络中,三个容器都分别获得了新的IP,在同一个网络中,容器相互之间可以用容器名称来调用服务,如mysql

修改配置

Nginx

打开/usr/local/docker/nginx/conf/nginx.conf,将下面的配置粘贴至 http 内。

server {    
    listen 443 ssl;
    server_name digu.plus www.digu.plus;
    
    ssl_certificate /etc/nginx/ssl/digu.plus_bundle.crt; # SSL 证书
    ssl_certificate_key /etc/nginx/ssl/digu.plus.key; # SSL 证书
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    location / {
        root   /www;
        index  index.html index.htm index.php;
        include /www/nginx.htaccess; # typecho 的伪静态
    }

    location ~ \.php$ {
        fastcgi_pass   php-fpm:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /www$fastcgi_script_name;
        include        fastcgi_params;
    }
}

server {
    listen 80;
    server_name digu.plus www.digu.plus;
    rewrite ^ https://$http_host$request_uri; # 强制使用 https 访问
}

MySQL

mysql 的容器创建好了,再来创建数据库。

# 进入 mysql 容器
docker exec -it mysql /bin/bash
# 登录 mysql
mysql -uroot -p
# 输入 root 密码
# 创建数据库
create database typecho

Typecho

将typecho的相关文件放入/usr/local/docker/nginx/blog,因为我是迁移,所以直接修改config.inc.php配置。如果是全新安装,这访问http://xxxx.com/install.php

// config db
$db = new \Typecho\Db('Pdo_Mysql', 'typecho_');
$db->addServer(array (
  'host' => 'mysql',
  'port' => 3306,
  'user' => 'root',
  'password' => 'password',
  'charset' => 'utf8mb4',
  'database' => 'typecho',
  'engine' => 'InnoDB',
), \Typecho\Db::READ | \Typecho\Db::WRITE);
\Typecho\Db::set($db);
  • 'host' => 'mysql'因为都在同一个网络,所以只需要写容器名称即可

结束

# 重启三个重启
docker restart nginx mysql php-pfm

Typecho 迁移至 Docker,至此迁移完成。