最近在學docker,先拿自己的博客來開下刀[手動狗頭]。
安裝docker
我是根據這個教程來安裝的:Centos安裝Docker。步驟如下:
- 卸載舊版本
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
- 安裝依賴包
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
- 添加yum源(建議使用國內鏡像)
sudo yum-config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
- 更新軟件源緩存並安裝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
即可。
- 啓動Docker CE
sudo systemctl enable docker
sudo systemctl start docker
- 測試Docker是否安裝正確
docker run hello-world
- 配置國內鏡像加速
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
容器與容器通信
現在機器上已經運行着nginx
、PHP
、mariadb
三個服務了,他們分別跑在宿主機的80(443)
、9000
、3306
端口上。我們現在需要做到的是讓nginx能夠使用php的服務,php能夠調用mariadb的服務,但容器間默認是互相隔離的,沒法直接通信,因此需要想辦法讓他們能夠互相通信。容器間的通信初次接觸會有點複雜,所以在這裏先和大家分享下一些要點。
通過了解,容器間通信主要會有以下幾種方法:
- 使用默認的
bridge
網絡,用網橋給容器分配的ip進行通信,官方不推薦用於生產環境。 - 自定義
bridge
網絡,可以通過容器名連接,官方推薦。 - 使用
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訪問,還支持直接使用容器名稱進行訪問,官方推薦使用在生產環境,因此我們會使用這種方式進行容器間的通信。
- 創建一個自定義網絡,名字可以隨意,如
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
- 容器使用自定義的網絡
如果容器尚未創建,可以在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
中數據庫相關的文件夾提取出來,如舊服務器有兩個名爲typecho
和test
的數據庫,就只將這兩個文件夾複製到新服務器的/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最爽的一點就是不用再關心怎麼安裝軟件的過程了,整個過程十分清爽。在整個過程中有幾點可以留意一下:
- 筆者將所有docker依賴的數據都掛載到宿主機的
/data
目錄中,是爲了方便管理和以後遷移; - 每個服務都是一個獨立的容器,不會互相影響。如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