Blog moving diary -- building a Docker based LNMP environment

Posted by dw89 on Mon, 22 Nov 2021 05:36:23 +0100

background

As the virtual machine is about to expire, we recently compared several cloud server providers. Finally decided to try UCloud . So I had to migrate the original blog (typecho). The following is a journal record of the process.

Process record

I wanted to try Previous notes Rebuild a set of environment and then import the data. However, it was a headache at the thought of this long series of steps and possible problems, so we decided to build a container based LNMP environment once and for all, which is also convenient for blog migration in the future. Of course, if some students also want to build a blog based on LNMP, such as 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

Because the environment is built with docker Therefore, first ensure that docker and docker compose are installed on the machine:

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

# Install 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 environment configuration

The construction is based on docker compose, and the directory structure is as follows:

.
├── docker-compose.yml # Docker compose configuration file
├── mysql
│   ├── conf # mysql configuration file directory
│   │   ├── my.cnf
│   └── data # mysql data file directory
├── nginx
│   ├── cert # nginx ssl certificate directory
│   │   ├── nightfield.com.cn.key
│   │   ├── nightfield.com.cn.pem
│   ├── conf # nginx configuration directory
│   │   ├── nightfield.com.cn.conf
│   ├── html # nginx Web root
│   │   ├── info.php
│   └── log # nginx log directory
├── php
│   ├── conf # php configuration directory
│   │   └── php.ini
│   └── Dockerfile # Dockerfile configuration for php

You can see some configuration files of the corresponding software. The contents of docker-compose.yml file are as follows:

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
            - /opt/docker/nginx/conf/:/etc/nginx/conf.d # configure 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 the construction of PHP is relatively complex, the Dockerfile method is used
            context: ./php
            dockerfile: Dockerfile
        container_name: php
        volumes:
            - /opt/docker/nginx/html:/usr/share/nginx/html # nginx web root
            - /opt/docker/php/conf/:/usr/local/etc/php/conf.d # configure 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 # configure 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:

Mysql

Mysql configuration is relatively simple and will not be repeated. Pay attention to mapping the corresponding configuration directory and data directory from the container for management.

Nginx

Map the configuration of Nginx from the container. The template is as follows:

# https ssl, corresponding to port 443
server {
    listen       443 ssl;
    server_name  nightfield.com.cn; # Domain name or server ip
    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 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(\/.*)*$ { # Notice the regularity 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, corresponding to port 80
server {
    listen 80;
    server_name nightfield.com.cn; # Domain name or server ip
    rewrite ^(.*)$ https://${server_name}$1 permanent; #  Redirect to https
}

PHP

The construction of PHP is relatively complex. In addition to pulling the PHP image from the official website, you also need to install additional modules, such as mysqli pdo_mysql, so a Dockerfile is made. The content is as follows:

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) \ # Plug in installation
        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 environment construction and verification

After the configuration is complete, start the container environment:

docker-componse up -d

In the security group rule configuration of ECs, open the corresponding port: 804433306 (you can close it after data migration), and then open the browser to access ${hostname}/info.php. You can see the following page:

Description: the environment has been installed successfully!

data migration

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

Typecho data

Package the entire Typecho directory and transfer it to the. / nginx/html / directory of the new machine with scp.

Mysql

I use the old-fashioned method here: export data from the old database and then import it into the new database. The tool is DBeaver . Here are some table structures related to 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;

Domain name re resolution

Go to the configuration page of the domain name, re resolve the A record to the new ip, wait for it to take effect (ping the following domain name to see the result), and then visit https://nightfield.com.cn The blog can be opened correctly. It still has the original taste, but the formula has been changed: -).

Problem record

1. The blog configuration is missing

I don't know the specific reason. I solved it in the stupidest way: the theme and plug-in were reconfigured.

2. PHP cannot connect to the database

The error reported is:

Uncaught Error: Class 'mysqli' not found

Generally, the reason is that mysqli is not installed, but we do install this module in Dockerfile. Add the following configuration to the configuration file. / php/conf/php.ini to solve the problem:

extension=mysqli.so
extension=pdo_mysql.so

3. Open many Typecho pages and report Cannot modify header information

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 102

Add the following configuration to the configuration file. / php/conf/php.ini to solve the problem:

output_buffering=on

4. Unable to log in to Typecho management page, report 404

This problem is caused by the failure to correctly parse the url. The url after Typecho login is similar https://www.nightfield.com.cn/index.php/action/login?_=7. The PHP location I configured in Nginx is location ~. * \. PHP $, which cannot handle the above url. Change location to location ~. * \. PHP (\ /. *) * $problem solved.

appendix

The code Github address of the docker based LNMP environment this time: Docker-LNMP.

Topics: docker compose Typecho