background

As the cloud host is about to expire, so recently compared several cloud server providers. Finally decided to give UCloud a try. The original blog (Typecho) had to be migrated. Here’s a rundown of the process.

The process records

I wanted to try to rebuild a set of environment according to the previous notes, and then import the data, but I felt a headache at the thought of such a long series of steps and possible problems, so I decided to build a container-based LNMP environment, once and for all, and it is convenient to continue the blog migration in the future. Of course, if you want to build an LNMP-based blog like Typecho, you can refer to my template 🙂 (Github link at the end of the article). Note: the following commands and configurations are based on CentOS7.

Container environment

Since docker is used to build the environment this time, docker and Docker-compose should be installed on the machine first:

# installation 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

# installation 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
Copy the code

LNMP environment configuration

Docker-compose directory structure:

. ├ ─ ─ docker - compose. YmlDocker-compose configuration file├── Mysql │ ├─ confMysql configuration file directory│ ├─ my. ├─ │ ├─Mysql data file directory├─ Nginx │ ├─ cert# nginx SSL certificate directory│ │ ├─ Nightfield.com.cn.key │ ├─ Nightfield.com.cn.pem │ ├── light school# nginx configuration directory│ ├─ Nightfield.com.cn.conf │ ├─ HTML# nginx Web root directory│ ├─ ├─ ├─ ├─log # nginx log directory├─ PHP │ ├─ conf# PHP configuration directory│ ├ ─ ├ ─ garbage │ ├ ─ garbage# PHP Dockerfile configuration
Copy the code

You can see mainly some configuration files for the corresponding software. Docker-comemess. yml file contains the following contents:

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 root directory
            - /opt/docker/nginx/conf/:/etc/nginx/conf.d # config directory
            - /opt/docker/nginx/log:/var/log/nginx # log directory
            - /opt/docker/nginx/cert:/etc/nginx/cert # SSL certificate directory
        links:
            - php
    php:
        build: Because PHP is relatively complex to build, Dockerfile is used
            context: ./php
            dockerfile: Dockerfile
        container_name: php
        volumes:
            - /opt/docker/nginx/html:/usr/share/nginx/html # nginx Web root directory
            - /opt/docker/php/conf/:/usr/local/etc/php/conf.d # config directory
        networks:
            - lnmp
        depends_on:
            - mysql
        expose:
            - "9000"
    mysql:
        image: Mysql: 5.7
        container_name: mysql
        volumes:
            - /opt/docker/mysql/conf/:/etc/mysql/conf.d # config directory
            - /opt/docker/mysql/data:/var/lib/mysql # Data directory
        environment:
            MYSQL_ROOT_PASSWORD: password # change to custom password
        networks:
            - lnmp
        expose:
            - "3306"
        ports:
            - "3306:3306"

networks:
    lnmp:
Copy the code

Mysql

The configuration of Mysql is simple and will not be described again. Map the configuration directory and data directory from the container for easy management.

Nginx

To map the Nginx configuration from the container, use the following template:

# HTTPS SSL, corresponding to port 443
server {
    listen       443 ssl;
    server_name  nightfield.com.cn; # Domain name or server IP address
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    index index.php;
    root         /usr/share/nginx/html;
    # SSL configuration
    ssl_certificate_key cert/nightfield.com.cn.key; Certificate of # key
    ssl_certificate cert/nightfield.com.cn.pem; # certificate pem
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_prefer_server_ciphers  on;

    location ~ .*\.php(\/.*)*$ { Note the re here
        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 for port 80
server {
    listen 80;
    server_name nightfield.com.cn; # Domain name or server IP address
    rewrite ^(.*)$ https://${server_name}$1 permanent; # redirect to HTTPS}Copy the code

PHP

PHP setup is relatively complex, in addition to pull the PHP image from the official website, also need to install additional modules such as mysqli pdo_mysql, so make a Dockerfile, the content is as follows:

The FROM PHP: 7.0 - FPM# Base image
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone
RUN apt-get update && apt-get install -y \ # Some lib libraries
        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) \ Install plugins
        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"]
Copy the code

LNMP environment construction and verification

When all configuration is complete, start the container environment:

docker-componse up -d
Copy the code

In the security group rule configuration of the cloud server, open the corresponding port:80.443.3306(Can be closed after data migration is complete), and then open a browser to access${hostname}/info.php, you can see the following page:The environment has been installed successfully.

Data migration

The next step is to migrate the blog data from the old library to the new library.

Typecho data

Package the entire Typecho directory and pass it with SCP to the./nginx/ HTML/directory on the new machine.

Mysql

I’m doing it the old-fashioned way: exporting data from the old library and importing it into the new library, using a tool called DBeaver. Here are some table structures associated with 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;
Copy the code

Domain name reresolution

Go to the configuration page of the domain name, re-resolve the A record to the new IP address, wait for the effect (ping the following domain name to see the result), visit nightfield.com.cn and you can open the blog correctly, the same taste, just change the formula :-).

The problem record

1. The blog configuration is lost

I don’t know why, but it was solved in the stupidest way possible: themes and plugins were reconfigured.

2. PHP cannot connect to the database

The error reported is:

Uncaught Error: Class 'mysqli' not found
Copy the code

Mysqli is not installed, but we do have this module installed in Dockerfile. / PHP /conf/php.ini

extension=mysqli.so
extension=pdo_mysql.so
Copy the code

3. The Cannot modify header information message is displayed on many Typecho pages

The error reported is:

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 102Copy the code

/ PHP /conf/php.ini

output_buffering=on
Copy the code

4. Failed to log in to the Typecho management page. 404 is reported

The problem is caused by an inability to parse urls properly. Typecho after landing the url of the similar * * www.nightfield.com.cn/index.php/a… Nginx configured PHP location as location ~.*\.php$, unable to handle the above url. PHP (\/.*)*$

The appendix

Docker-based LNMP environment code Github address: docker-lnMP.