背景
由於雲主機馬上就要到期了,所以最近對比了幾家雲服務器提供商。最終決定嘗試一下 UCloud。於是不得不把原博客(typecho)遷移過來。下面是流水賬式地記錄一下過程。
過程記錄
本想嘗試按照以前的筆記重新搭建一套環境,然後再把數據導過來,但是一想到這一長串的步驟,以及可能碰到的問題就頭疼,於是決定構建一個基於容器的 LNMP 環境,一勞永逸,也方便日後繼續做博客遷移。當然如果有同學也想搭建基於 LNMP 的博客如 Typecho,則可以參考我的模板:-)(文末有 Github 鏈接)。 注:以下命令及配置都是基於 CentOS7。
容器環境
由於此次環境的搭建是用的 docker,所以先保證機器上安裝了 docker 和 docker-compose:
# 安裝 docker
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl enable docker
sudo systemctl start docker
# 安裝 docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
LNMP 環境配置
構建基於 docker-compose
,目錄結構如下:
.
├── docker-compose.yml # docker-compose 配置文件
├── mysql
│ ├── conf # mysql 配置文件目錄
│ │ ├── my.cnf
│ └── data # mysql 數據文件目錄
├── nginx
│ ├── cert # nginx ssl 證書目錄
│ │ ├── nightfield.com.cn.key
│ │ ├── nightfield.com.cn.pem
│ ├── conf # nginx 配置目錄
│ │ ├── nightfield.com.cn.conf
│ ├── html # nginx Web 根目錄
│ │ ├── info.php
│ └── log # nginx 日誌目錄
├── php
│ ├── conf # php 配置目錄
│ │ └── php.ini
│ └── Dockerfile # php 的 Dockerfile 配置
可以看到主要是對應軟件的一些配置文件。docker-compose.yml
文件內容如下:
version: "3"
services:
nginx:
image: nginx:latest
container_name: nginx
networks:
- lnmp
depends_on:
- php
ports:
- "80:80"
- "443:443"
expose:
- "80"
- "443"
volumes:
- /opt/docker/nginx/html:/usr/share/nginx/html # nginx web 根目錄
- /opt/docker/nginx/conf/:/etc/nginx/conf.d # 配置目錄
- /opt/docker/nginx/log:/var/log/nginx # 日誌目錄
- /opt/docker/nginx/cert:/etc/nginx/cert # ssl 證書目錄
links:
- php
php:
build: # 由於 PHP 的構建相對較爲複雜,所以用了 Dockerfile 的方式
context: ./php
dockerfile: Dockerfile
container_name: php
volumes:
- /opt/docker/nginx/html:/usr/share/nginx/html # nginx web 根目錄
- /opt/docker/php/conf/:/usr/local/etc/php/conf.d # 配置目錄
networks:
- lnmp
depends_on:
- mysql
expose:
- "9000"
mysql:
image: mysql:5.7
container_name: mysql
volumes:
- /opt/docker/mysql/conf/:/etc/mysql/conf.d # 配置目錄
- /opt/docker/mysql/data:/var/lib/mysql # 數據目錄
environment:
MYSQL_ROOT_PASSWORD: password # 改爲自定義密碼
networks:
- lnmp
expose:
- "3306"
ports:
- "3306:3306"
networks:
lnmp:
Mysql
Mysql 的配置較爲簡單不再贅述,注意將對應的配置目錄以及數據目錄從容器中映射出來便於管理。
Nginx
將 Nginx 的配置從容器中映射出來,模版如下:
# https ssl, 對應 443 端口
server {
listen 443 ssl;
server_name nightfield.com.cn; # 域名或者服務器 ip
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
index index.php;
root /usr/share/nginx/html;
# ssl 配置
ssl_certificate_key cert/nightfield.com.cn.key; # 證書 key
ssl_certificate cert/nightfield.com.cn.pem; # 證書 pem
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_prefer_server_ciphers on;
location ~ .*\.php(\/.*)*$ { # 注意這裏的正則
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
# https,對應 80 端口
server {
listen 80;
server_name nightfield.com.cn; # 域名或者服務器 ip
rewrite ^(.*)$ https://${server_name}$1 permanent; # 重定向到 https
}
PHP
PHP 的構建相對複雜,除了從官網拉 PHP 鏡像外,還需要安裝額外的模塊如 mysqli pdo_mysql,所以做了一個 Dockerfile
,內容如下:
FROM php:7.0-fpm # 基礎鏡像
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
RUN apt-get update && apt-get install -y \ # 一些 lib 庫
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng-dev \
libmemcached-dev \
zlib1g-dev \
libcurl4-openssl-dev \
libxml2-dev \
--no-install-recommends && rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-install -j$(nproc) \ # 插件安裝
iconv mcrypt gettext curl mysqli pdo pdo_mysql zip \
mbstring bcmath opcache xml simplexml sockets hash soap \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd
CMD ["php-fpm", "-F"]
LNMP 環境構建及驗證
配置都完成之後,啓動容器環境:
docker-componse up -d
在雲服務器的安全組規則配置中,開放對應端口:80,443,3306(完成數據遷移之後可以關閉),然後打開瀏覽器訪問 ${hostname}/info.php
,可以看到如下頁面: 說明環境已安裝成功!
數據遷移
接下來要做的就是把博客數據從老的庫遷移到新的庫。
Typecho 數據
將整個 Typecho 目錄打包,用 scp
傳到新機器的 ./nginx/html/
目錄下。
Mysql
我這裏用了比較老套的方法:從老庫導出數據再導入新庫,用工具是 DBeaver。這裏記錄一下 Typecho 相關的一些表結構。
use typecho;
CREATE TABLE `typecho_comments` (
`coid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cid` int(10) unsigned DEFAULT '0',
`created` int(10) unsigned DEFAULT '0',
`author` varchar(200) DEFAULT NULL,
`authorId` int(10) unsigned DEFAULT '0',
`ownerId` int(10) unsigned DEFAULT '0',
`mail` varchar(200) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
`ip` varchar(64) DEFAULT NULL,
`agent` varchar(200) DEFAULT NULL,
`text` text,
`type` varchar(16) DEFAULT 'comment',
`status` varchar(16) DEFAULT 'approved',
`parent` int(10) unsigned DEFAULT '0',
PRIMARY KEY (`coid`),
KEY `cid` (`cid`),
KEY `created` (`created`)
) ENGINE=MyISAM AUTO_INCREMENT=51476 DEFAULT CHARSET=utf8;
CREATE TABLE `typecho_contents` (
`cid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
`slug` varchar(200) DEFAULT NULL,
`created` int(10) unsigned DEFAULT '0',
`modified` int(10) unsigned DEFAULT '0',
`text` longtext,
`order` int(10) unsigned DEFAULT '0',
`authorId` int(10) unsigned DEFAULT '0',
`template` varchar(32) DEFAULT NULL,
`type` varchar(16) DEFAULT 'post',
`status` varchar(16) DEFAULT 'publish',
`password` varchar(32) DEFAULT NULL,
`commentsNum` int(10) unsigned DEFAULT '0',
`allowComment` char(1) DEFAULT '0',
`allowPing` char(1) DEFAULT '0',
`allowFeed` char(1) DEFAULT '0',
`parent` int(10) unsigned DEFAULT '0',
`views` int(10) DEFAULT '0',
PRIMARY KEY (`cid`),
UNIQUE KEY `slug` (`slug`),
KEY `created` (`created`)
) ENGINE=MyISAM AUTO_INCREMENT=199 DEFAULT CHARSET=utf8;
CREATE TABLE `typecho_fields` (
`cid` int(10) unsigned NOT NULL,
`name` varchar(200) NOT NULL,
`type` varchar(8) DEFAULT 'str',
`str_value` text,
`int_value` int(10) DEFAULT '0',
`float_value` float DEFAULT '0',
PRIMARY KEY (`cid`,`name`),
KEY `int_value` (`int_value`),
KEY `float_value` (`float_value`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `typecho_metas` (
`mid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL,
`slug` varchar(200) DEFAULT NULL,
`type` varchar(32) NOT NULL,
`description` varchar(200) DEFAULT NULL,
`count` int(10) unsigned DEFAULT '0',
`order` int(10) unsigned DEFAULT '0',
`parent` int(10) unsigned DEFAULT '0',
PRIMARY KEY (`mid`),
KEY `slug` (`slug`)
) ENGINE=MyISAM AUTO_INCREMENT=52 DEFAULT CHARSET=utf8;
CREATE TABLE `typecho_options` (
`name` varchar(32) NOT NULL,
`user` int(10) unsigned NOT NULL DEFAULT '0',
`value` text,
PRIMARY KEY (`name`,`user`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `typecho_relationships` (
`cid` int(10) unsigned NOT NULL,
`mid` int(10) unsigned NOT NULL,
PRIMARY KEY (`cid`,`mid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `typecho_users` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL,
`mail` varchar(200) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
`screenName` varchar(32) DEFAULT NULL,
`created` int(10) unsigned DEFAULT '0',
`activated` int(10) unsigned DEFAULT '0',
`logged` int(10) unsigned DEFAULT '0',
`group` varchar(16) DEFAULT 'visitor',
`authCode` varchar(64) DEFAULT NULL,
PRIMARY KEY (`uid`),
UNIQUE KEY `name` (`name`),
UNIQUE KEY `mail` (`mail`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
域名重解析
去域名的配置頁面,將 A 記錄 重新解析到新的 ip 上,等待生效後(ping
以下域名看結果),訪問 https://nightfield.com.cn 已經可以正確打開博客,還是原來的味道,只是換了配方:-)。
問題記錄
1. 博客的配置丟失
還不知道具體原因,用最笨的方法解決了:主題和插件重新配置了一下。
2. PHP 無法連接數據庫
報的錯誤是:
Uncaught Error: Class 'mysqli' not found
原因一般是沒有安裝 mysqli
導致的,但是我們在 Dockerfile
裏面確實有安裝此模塊。在配置文件 ./php/conf/php.ini
中加上以下配置,問題解決:
extension=mysqli.so
extension=pdo_mysql.so
3. 打開很多 Typecho 頁面報 Cannot modify header information
報的錯誤是:
Warning: Cannot modify header information - headers already sent by (output started at /data/dy-pages/store-1/262/1634262/www/install.php:202) in /data/dy-pages/store-1/262/1634262/www/var/Typecho/Cookie.php on line 102
在配置文件 ./php/conf/php.ini
中加上以下配置,問題解決:
output_buffering=on
4. 無法登陸 Typecho 管理頁面,報 404
這個問題是無法正確解析 URL 導致的。Typecho 登陸之後的 url 類似 https://www.nightfield.com.cn/index.php/action/login?_=7,而我在 Nginx 配置的 PHP location 爲 location ~ .*\.php$
,無法處理上述 url。將 location 改爲 location ~ .*\.php(\/.*)*$
問題解決。
附錄
本次基於 docker 的 LNMP 環境的代碼 Github 地址:Docker-LNMP。