Centos8使用docker遷移typecho博客

最近在學docker,先拿自己的博客來開下刀[手動狗頭]。

安裝docker

我是根據這個教程來安裝的:Centos安裝Docker。步驟如下:

  1. 卸載舊版本
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine
  1. 安裝依賴包
sudo yum install -y yum-utils \
           device-mapper-persistent-data \
           lvm2
  1. 添加yum源(建議使用國內鏡像)
sudo yum-config-manager \
    --add-repo \
    https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
  1. 更新軟件源緩存並安裝docker-ce
sudo yum makecache fast
sudo yum install docker-ce

sudo yum install docker-ce這一步可能會報錯:containerd.io (>= 1.2.2-3),此時需要先安裝新版本的containerd.io

yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm

最新的containerd.io版本請在https://download.docker.com/linux/centos/7/x86_64/stable/Packages/找(國內直接安裝containerd.io可能會非常慢導致安裝失敗,建議可以想辦法將rpm包下載到本機再安裝)。安裝完containerd.io後再sudo yum install docker-ce即可。

  1. 啓動Docker CE
sudo systemctl enable docker
sudo systemctl start docker
  1. 測試Docker是否安裝正確
docker run hello-world
  1. 配置國內鏡像加速
    vi /etc/docker/daemon.json(該文件不存在時請新建)
{
  "registry-mirrors": [
    "https://dockerhub.azk8s.cn",
    "https://reg-mirror.qiniu.com"
  ]
}

保存後重啓服務

sudo systemctl daemon-reload
sudo systemctl restart docker

安裝mariadb

mkdir -p /data/mariadb
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=test --mount type=bind,source=/data/mariadb,target=/var/lib/mysql --restart=always --name mariadb mariadb

--mount命令也可以用-v /data/mariadb:/var/lib/mysql --name mariadb mariadb代替,官方更推薦使用--mount,詳情請看官網

參數說明:

  • -d 代表 daemon,即後臺運行
  • -p是映射容器的3306端口到宿主機的3306端口,規則是:-p IP:host_port:container_port
  • -e是設置mariadb的密碼
  • --mount是讓容器的/var/lib/mysql映射到宿主機的/data/mariadb目錄中
  • --restart=always是爲了在docker重啓時,容器能夠自動啓動

PS: 後面筆者會將所有容器依賴的一些數據都放在/data目錄下,包括數據庫、網站源碼、nginx的conf等,目的是爲了以後遷移方便,直接將/data拷貝到新服務器就可以。

安裝nginx

mkdir -p /data/nginx/conf.d
docker run -p 80:80 -p 443:443 --mount type=bind,source=/data/nginx/conf.d,target=/etc/nginx/conf.d --mount type=bind,source=/data/solution,target=/data/solution --restart=always -d --name nginx nginx

說明:

  • --mount type=bind,source=/data/nginx/conf.d,target=/etc/nginx/conf.d是爲了將nginx的配置目錄映射到宿主機的目錄中,這樣當nginx容器被銷燬時,依然能保留配置。
  • /data/solution用於存放網站項目,也是爲了數據與容器分離。
  • -d這裏同時映射了80和443端口

安裝php

可以在php的官方鏡像源找到最新版本的php,在實際使用中,我們可能還需要裝一些php的擴展,而官方源中支持已經幫我們安裝了一些擴展的php鏡像,如:php:<version>-fpm,其中的<version>指的是php版本,具體可以從官方鏡像源找到,當前最高版本是7.4。

docker run --name php-fpm -p 9000:9000 --mount type=bind,source=/data/solution,target=/data/solution --restart=always -d php:7.4-fpm

這裏也將網站根目錄/data/solution映射到php容器中,爲了php能正確讀取nginx中的root配置項。

由於typecho需要用到pdo_mysql擴展,因此要在php-fpm上安裝這個擴展。

# 進入到`php-fpm`容器內部
docker exec -it php-fpm bash
# 安裝擴展
docker-php-ext-install pdo_mysql
# 查看是否已經成功安裝
php -m
# 退出容器
exit

容器與容器通信

現在機器上已經運行着nginxPHPmariadb三個服務了,他們分別跑在宿主機的80(443)90003306端口上。我們現在需要做到的是讓nginx能夠使用php的服務,php能夠調用mariadb的服務,但容器間默認是互相隔離的,沒法直接通信,因此需要想辦法讓他們能夠互相通信。容器間的通信初次接觸會有點複雜,所以在這裏先和大家分享下一些要點。

通過了解,容器間通信主要會有以下幾種方法:

  1. 使用默認的bridge網絡,用網橋給容器分配的ip進行通信,官方不推薦用於生產環境。
  2. 自定義bridge網絡,可以通過容器名連接,官方推薦
  3. 使用host網絡共用宿主機的網絡。

很多早期的文章分享都會使用--link參數來指定容器通信,但這種方法已經是過時的了,官方不再推薦使用,所以咱們這裏也就不再用了,用官方推薦的方法更好。

使用默認的bridge網絡

啓動容器時,docker默認會將自動將容器綁定到默認的bridge網絡中。打印一下默認的網絡:

$ docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

然後再看一下都有哪些容器連接到了bridge網絡:

docker network inspect bridge

可以看到mariadb,nginx,php-fpm的在bridge中的ip分別是172.17.0.4,172.17.0.2,172.17.0.3,宿主機的ip是172.17.0.1

我們可以通過在容器中通過宿主機的ip來訪問對應的服務,即php-fpm想要訪問mariadb,可以在php-fpm容器中通過172.17.0.1:3306來訪問。

這種方式只能使用ip來訪問對應的容器的服務,而ip可能會變化的,因此是不推薦使用在生產環境的,所以我們不會使用這種方式。

使用自定義bridge網絡

除了默認的bridge網絡,官方推薦用戶自定義一個bridge網絡用作生產環境,用戶自定義的bridge網絡不僅支持ip訪問,還支持直接使用容器名稱進行訪問,官方推薦使用在生產環境,因此我們會使用這種方式進行容器間的通信。

  1. 創建一個自定義網絡,名字可以隨意,如typecho
docker network create typecho

打印一下當前的network,可以看到typecho已經存在了。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
429eabf557a3        bridge              bridge              local
3f47e77c0ded        host                host                local
3784484fb92e        typecho             bridge              local
7ff63bc6d9bd        none                null                local
  1. 容器使用自定義的網絡

如果容器尚未創建,可以在docker run命令時通過--network參數來指定網絡,如

docker run -d --name mynginx --network typecho nginx

如果容器已經在運行了,我們也可以通過docker network connect ${網絡名} ${容器名}來指定,在上面我們已經運行了mariadb,php-fpm,nginx,所以現在依次爲他們都綁定到typecho網絡中。

docker network connect typecho mariadb
docker network connect typecho php-fpm
docker network connect typecho nginx

檢查一下綁定到typecho網絡的容器

$ docker network inspect typecho
[
    {
        "Name": "typecho",
        "Id": "3784484fb92e36c1448d2303af1b8bdce680e2cba0452fca354cefb6cb81bb54",
        "Created": "2019-12-08T08:32:57.299750734-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "6c644a890f3d1e7cc9e846236b6467ac31084470289fba5f6af1c2c1a0171e8e": {
                "Name": "mariadb",
                "EndpointID": "881c4f00a8d15f4e941d50faf53846a3ab8f15772fccc5e8c568e8d97b346b3b",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "f98355c7b220c0ab2897aa2478037e3322d78ccd81518af7a4756b07e1e26719": {
                "Name": "nginx",
                "EndpointID": "f14e5c36fcfe7ac5f26b8495335366957b6d7ab6d59c13e55cae2f1dc7751929",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "f9cb6cfcebf6f82beca76d3061765c1deb482a9c3c30d0c6d3644fe10ae40e3e": {
                "Name": "php-fpm",
                "EndpointID": "c4a2e26fe887e04f01a36eea9771eb2e817ef29d1bd7c435b380a7ca18485e64",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

可以看到mariadb,php-fpm,nginx都已經連接到typecho網絡了。這樣,我們在nginx容器,就可以直接通過php-fpm的名字來調用php的服務了。

使用host網絡

如果容器使用了host網絡,即docker運行時通過--network host來指定容器的網絡,會使得容器共享宿主機的網絡配置,即容器的localhost就是宿主機的localhost。

直接使用Docker host網絡最大的好處就是性能更好,如果容器對網絡傳輸效率有較高要求,則可以選擇host網絡。當然不便之處就是犧牲一些靈活性,比如要考慮端口衝突問題,Docker host上已經使用的端口就不能再用了。

我們這裏暫時不使用這種方式。

遷移typecho博客

遷移數據庫

由於是第一次遷移,新舊兩個數據庫的配置可能會有些不一樣,所以爲了不改變新服務器的一些配置,我們只遷移mariadb中涉及到數據的部分。

具體操作就是: 將原服務器/var/lib/mysql中數據庫相關的文件夾提取出來,如舊服務器有兩個名爲typechotest的數據庫,就只將這兩個文件夾複製到新服務器的/data/mariadb中,然後重啓一下mariadb即可:docker restart mariadb

PS: 還有一種遷移辦法是可以選擇將舊服務器的數據庫備份成sql文件,然後在新服務器做還原哦。

遷移typecho源碼

筆者這裏將typecho的源代碼放到/data/solution/typecho文件夾中。

配置nginx

vi /data/nginx/conf.d/typecho.conf

server {
  listen       80;
  server_name  localhost;
  location / {
    try_files $uri $uri/ /index.php?$args;
  }
  location ~ .php$ {
    root      /data/solution/typecho;
    fastcgi_pass  php-fpm:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include       fastcgi_params;
  }
}

server_name我這裏寫了localhost,暫時算是本地測試一下,實際使用時會改成域名。

修改nginxi配置後需要重啓一下nginx的鏡像才能生效:docker restart nginx

typecho的配置文件config.inc.php

注意數據庫連接的配置,數據庫的host可以直接使用mariadb,因爲前面將兩個容器綁在了同一個網絡,php能正常解析到。

/** .... */

/** 定義數據庫參數 */
$db = new Typecho_Db('Pdo_Mysql', 't_');
$db->addServer(array (
  'host' => 'mariadb',
  'user' => 'root',
  'password' => 'YOUR_PASSWORD',
  'charset' => 'utf8',
  'port' => '3306',
  'database' => 'typecho',
), Typecho_Db::READ | Typecho_Db::WRITE);
Typecho_Db::set($db);

至此,整個遷移過程就完成了,可以用curl localhost測試一下或在瀏覽器中直接使用服務器的ip來訪問頁面啦。

PS: 記得不要忘了要打開服務器的80端口防火牆哦~~

Tips: 如果沒法正常啓動typecho,可能是某一步配置的不對,可以通過docker logs <container_name>命令查看對應容器的日誌,然後查找相關的解決辦法哦。附上兩篇typecho解決錯誤的文章:Typecho 部署踩坑, 安裝Typecho卡在“確認您的配置,數據庫配置”問題的終極解決方法

總結

用上docker最爽的一點就是不用再關心怎麼安裝軟件的過程了,整個過程十分清爽。在整個過程中有幾點可以留意一下:

  1. 筆者將所有docker依賴的數據都掛載到宿主機的/data目錄中,是爲了方便管理和以後遷移;
  2. 每個服務都是一個獨立的容器,不會互相影響。如mariadb除了可以爲我的博客系統服務,也可以給其他的服務調用;nginx也支持多站點,只需要/data/nginx/conf.d增加一個配置。

由於是第一次用上docker遷移,第一次會有點折騰,但以後再遷移就會方便多了。整個流程大概會是這樣子:

# 在新服務器拉取舊服務器的數據
scp -r root@<old_server_ip>:/data /data/

# 安裝docker-ce

# 新建一個網絡
docker network create typecho

# 分別啓動mariadb,php-fpm,nginx三個容器,並綁定typecho網絡
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=test --mount type=bind,source=/data/mariadb,target=/var/lib/mysql --restart=always --network typecho --name mariadb mariadb
docker run --name php-fpm -p 9000:9000 --mount type=bind,source=/data/solution,target=/data/solution --restart=always --network typecho -d php:7.4-fpm
docker run -p 80:80 -p 443:443 --mount type=bind,source=/data/nginx/conf.d,target=/etc/nginx/conf.d --mount type=bind,source=/data/solution,target=/data/solution --restart=always --network typecho -d --name nginx nginx

# 安裝php擴展
docker exec -i php-fpm docker-php-ext-install pdo_mysql

# 測試走起
curl localhost
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章