admin 发布的文章

Docker部署

  1. 创建配置文件

    [root@ecs ~]# mkdir -p /data/redis
    [root@ecs ~]# cat >> /data/redis/redis.conf << EOF
    bind 0.0.0.0
    daemonize no
    protected-mode no
    requirepass IoujIYFehq24200S
    appendonly yes
    EOF
    • daemonize:是否以守护线程方式启动,默认no。
    • appendonly:是否持久化数据,默认no。
  2. 创建容器

    [root@ecs ~]# docker run --name=redis \
    --privileged=true \
    -p 6379:6379 \
    -v /data/redis:/etc/redis \
    -v /data/redis/data:/data \
    -d --restart=always maisi/redis:8.4.0 redis-server /etc/redis/redis.conf --appendonly yes
    • --privileged=true:容器内的root用户拥有宿主机root权限,否则容器内root用户只是外部普通用户权限;
    • --appendonly yes:开启数据持久化(如果配置文件中已配置,可忽略)
  3. 防火墙放行

    [root@ecs ~]# firewall-cmd --zone=public --add-port=6379/tcp --permanent
    [root@ecs ~]# firewall-cmd --reload

部署Docker

安装Docker

CentOS 7.9

  1. 配置yum源

    [root@ecs ~]# yum install -y yum-utils
    [root@ecs ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  2. 安装docker ce

    yum install -y docker-ce
  3. 启动docker并设置开机自启动

    [root@ecs ~]# systemctl enable --now docker
  4. 查看docker版本

    [root@ecs ~]# docker --version
    Docker version 26.1.4, build 5650f9b
  5. 安装docker compose

    [root@ecs ~]# curl -L "https://gh-proxy.com/https://github.com/docker/compose/releases/download/v2.29.7/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    [root@ecs ~]# chmod a+x /usr/local/bin/docker-compose
    [root@ecs ~]# docker-compose version
    Docker Compose version v2.29.7

Ubuntu

Docker要求内核版本不能低于3.10,且必须为64位系统。

  1. 查看Ubuntu内核版本

    root@ecs:~# uname -a
    Linux ecs 5.15.0-186-generic #196-Ubuntu SMP Sat Jun 20 16:09:34 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
  2. 更换软件源

    Ubuntu 22.4

    root@ecs:~# sed -i 's|http://[a-z0-9\.]*\.archive\.ubuntu\.com|https://mirrors.aliyun.com|g;s|http://security\.ubuntu\.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list
    root@ecs:~# apt update && apt upgrade && apt full-upgrade

    Ubuntu 24.4

    root@ecs:~# sed -i 's|http://[a-z0-9\.]*\.archive\.ubuntu\.com|https://mirrors.aliyun.com|g;s|http://security\.ubuntu\.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list.d/ubuntu.sources
    root@ecs:~# apt update && apt upgrade && apt full-upgrade
  3. 安装Docker

    root@ecs:~# curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
    root@ecs:~# add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
    root@ecs:~# apt install docker-ce

    注:必须添加GPG key,否则会报错:

    W: GPG error: http://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
    E: The repository 'http://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy InRelease' is not signed.`。

    Ubuntu 26.04已从apt(2.9.17+)移除了apt-key,因此不再适用上面的方法,需要先使用gpg --dearmor下载并转换密钥,然后通过signed-by在软件源中指定该密钥。

    root@ecs:~# curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | \
    gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    root@ecs:~# echo "deb [signed-by=/etc/apt/keyrings/docker.gpg] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | \
    tee /etc/apt/sources.list.d/docker.list
    root@ecs:~# apt-get update && apt-get install docker-ce
  4. 启动docker

    root@ecs:~# systemctl start docker

镜像管理

  • 拉取镜像

    [root@ecs ~]# docker pull registry.cn-shanghai.aliyuncs.com/maisi/alpine:latest
  • 导入镜像

    [root@ecs ~]# docker load < php_8.2-fpm-amd64.tar
  • 设置标签(仓库地址)

    [root@ecs ~]# docker tag php:8.2-fpm registry.cn-shanghai.aliyuncs.com/maisi/php:8.2-fpm
  • 上传镜像

    [root@ecs ~]# docker login --username=hi30772550@aliyun.com registry.cn-shanghai.aliyuncs.com 
    [root@ecs ~]# docker push registry.cn-shanghai.aliyuncs.com/maisi/php:8.2-fpm
    [root@ecs ~]# docker rmi registry.cn-shanghai.aliyuncs.com/maisi/php:8.2-fpm
  • 加速镜像

    [root@ecs ~]# cat > /etc/docker/daemon.json << EOF
    {
        "registry-mirrors": [
            "http://mscr.o88.co",
            "https://registry.cn-shanghai.aliyuncs.com"
        ],
        "insecure-registries": [
            "mscr.o88.co"
        ]
    }
    EOF
    [root@ecs ~]# systemctl daemon-reload
    [root@ecs ~]# systemctl restart docker

    默认情况下,镜像地址必须使用https,否则会报错:Error response from daemon: Get "https://mscr.o88.co/v2/": http: server gave HTTP response to HTTPS client。将镜像地址加入insecure-registries列表则可以不使用https协议传输。

    之后便可以直接使用以下方式拉取镜像:

    [root@ecs ~]# docker pull maisi/php:8.2-fpm  

    验证镜像设置是否生效:

    [root@ecs ~]# docker info | grep -A 2 'Registry'
     Registry Mirrors:
      http://mscr.o88.co/
      https://registry.cn-shanghai.aliyuncs.com/
  • 缓存docker yum源

    [root@ecs ~]# yum install -y createrepo
    [root@ecs ~]# reposync -np /data
    [root@ecs ~]# createrepo -po /data/docker-ce-stable /data/docker-ce-stable

    createrepo -po <元数据输出目录> <RPM包目录>:创建yum软件仓库元数据。

应用

部署php

安装GD

  1. 编写Dockerfile

    FROM php:8.2-fpm
    
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
    && echo $TZ > /etc/timezone
    RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources
    
    RUN apt-get update && apt-get install -y \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    && rm -rf /var/lib/apt/lists/*
    
    RUN docker-php-ext-configure gd \
    --with-freetype \
    --with-jpeg
    
    RUN docker-php-ext-install -j$(nproc) gd pdo_mysql mysqli
    • Debian 12废弃了/etc/apt/sources.list,需改成:/etc/apt/sources.list.d/debian.sources
    • GD(Graphics Draw)是php动态创建和处理图像的核心扩展库,强制依赖libpng-dev,安装libfreetype6-dev时会自动安装libpng-dev,如果没有安装libfreetype6-dev则必须手动安装libpng-dev
    • --with-freetype为GD启用freetype字体库支持,--with-jpeg为GD启用jpeg支持。
  2. 编译镜像

    [root@ecs ~]# docker build -t php:8.2-fpm-ext .

运行php

[root@ecs ~]# docker run --name php \
--privileged=true \
--restart=always \
-e TZ=Asia/Shanghai \
-v /data/wwwroot:/var/www \
-v /tmp:/tmp \
-p 9000:9000 \
-d php:8.2-fpm-ext

Docker部署

  1. 拉取基础镜像

    [root@ecs ~]# docker pull registry.cn-shanghai.aliyuncs.com/maisi/node:22-alpine
    [root@ecs ~]# docker tag registry.cn-shanghai.aliyuncs.com/maisi/node:22-alpine node:22-alpine
    [root@ecs ~]# docker pull registry.cn-shanghai.aliyuncs.com/maisi/golang:1.25.11-bookworm
    [root@ecs ~]# docker tag registry.cn-shanghai.aliyuncs.com/maisi/golang:1.25.11-bookworm golang:1.25.11-bookworm
  2. 构建镜像

    [root@ecs ~]# unzip tianji-master.zip
    [root@ecs ~]# cd tianji-master
    [root@ecs tianji-master]# cat > ./debian.tmp << 'EOF'
    RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources && \
        sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources && \
        apt-get update && \
        apt-get install -y --no-install-recommends git ca-certificates tzdata && \
        rm -rf /var/lib/apt/lists/*
    
    ENV GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
    EOF
    [root@ecs tianji-master]# sed -i '/AS reporter/r ./debian.tmp' Dockerfile
    [root@ecs tianji-master]# sed -i '/AS base/a\RUN sed -i '\''s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g'\'' /etc/apk/repositories' Dockerfile
    [root@ecs tianji-master]# sed -i '/pnpm@10.27.0/s#$# --registry=https://registry.npmmirror.com#g' Dockerfile
    [root@ecs tianji-master]# sed -i '/AS static/a\RUN pnpm config set registry https://registry.npmmirror.com' Dockerfile
    [root@ecs tianji-master]# sed -i '/AS app/a\RUN pnpm config set registry https://registry.npmmirror.com' Dockerfile
    [root@ecs tianji-master]# sed -i '/ENV VITE_VERSION/i\ENV VERCEL=true' Dockerfile
    [root@ecs tianji-master]# sed -i '/COPY --from=static \/app\/tianji\/geo/s/^/# /g' Dockerfile
    [root@ecs tianji-master]# docker build -t tianji .
  3. 创建容器

    [root@ecs ~]# docker run --name tianji \
    --restart=unless-stopped \
    -e DATABASE_URL=postgresql://tianji:xpzTkwEL1IcU28dF@192.168.1.3:5432/tianji_db?schema=public \
    -p 12345:12345 \
    -v /data/tianji/geo/GeoLite2-City.mmdb:/app/tianji/geo/GeoLite2-City.mmdb:rw \
    -d tianji

    管理地址:http://192.168.3.103:12345/login,初始用户名/密码:admin/admin。

安装

Windows

mysql 5.7.40

  1. 创建my.ini

    [mysql]
    default_character_set=utf8mb4
    
    [mysqld]
    port=3306
    basedir=D:/usr/local/mysql/
    datadir=D:/usr/local/mysql/data
    max_connections=200
    character_set_server=utf8mb4
    default_storage_engine=INNODB
    lower_case_table_names=1
    default_time_zone='+8:00'
  2. 初始化数据库

    D:\>cd D:\usr\local\mysql\bin
    D:\usr\local\mysql\bin>mysqld --initialize --user=mysql --console --explicit_defaults_for_timestamp
    2025-06-20T13:25:08.995251Z 0 [Warning] InnoDB: New log files created, LSN=45790
    2025-06-20T13:25:09.081107Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
    2025-06-20T13:25:09.175719Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: fcb9b279-4dd9-11f0-bcff-3c970e3c7ec6.
    2025-06-20T13:25:09.197778Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
    2025-06-20T13:25:10.723739Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
    2025-06-20T13:25:10.727148Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
    2025-06-20T13:25:10.730535Z 0 [Warning] CA certificate ca.pem is self signed.
    2025-06-20T13:25:10.937104Z 1 [Note] A temporary password is generated for root@localhost: if<d/xGoY6#?

    if<d/xGoY6#?为自动生成的root密码。

  3. 注册服务

    D:\usr\local\mysql\bin>mysqld --install MySQL --defaults-file="D:\usr\local\mysql\my.ini"
    Service successfully installed.
  4. 启动服务

    D:\usr\local\mysql\bin>net start mysql
  5. 删除服务

    D:\usr\local\mysql\bin>net stop mysql
    D:\usr\local\mysql\bin>mysqld --remove MySQL

mysql 8.0

  1. 创建my.ini

    [mysql]
    default_character_set=utf8mb4
    
    [mysqld]
    port=3306
    basedir=D:/usr/local/mysql/
    datadir=D:/usr/local/mysql/data
    max_connections=200
    character_set_server=utf8mb4
    default_storage_engine=INNODB
    lower_case_table_names=1
    default_time_zone='+8:00'
    
    server_id=1
    log_bin=D:/usr/local/mysql/log/bin
    log_bin_index=D:/usr/local/mysql/log/bin.index
    expire_logs_days=7
    binlog_format=ROW
    #binlog_do_db=mysql
    #binlog_ignore_db=mysql
    max_binlog_size=100M
    binlog_cache_size=4M
    max_binlog_cache_size=512M
    
    plugin_load_add=validate_password.dll

    plugin_load_add=validate_password.dll开启密码策略管理。

    查看密码策略是否生效:

    mysql> show variables like 'validate%';
  2. 初始化数据库

    D:\usr\local\mysql\bin>mysqld --initialize --user=mysql --console
    2025-06-20T14:42:31.134143Z 0 [System] [MY-013169] [Server] D:\usr\local\mysql\bin\mysqld.exe (mysqld 8.0.31) initializing of server in progress as process 6016
    2025-06-20T14:42:31.169182Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
    2025-06-20T14:42:32.051844Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
    2025-06-20T14:42:32.690248Z 0 [Warning] [MY-013501] [Server] Ignoring --plugin-load[_add] list as the server is running with --initialize(-insecure).
    2025-06-20T14:42:35.467199Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: 9lc?BR72%c?L
  3. 注册服务

    D:\usr\local\mysql\bin>mysqld install MySQL
  4. 启动服务

    D:\usr\local\mysql\bin>net start MySQL

CentOS 7.9

mysql 5.6.37

  1. 安装mysql

    [root@ecs ~]# sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
    [root@ecs ~]# setenforce 0
    [root@ecs ~]# groupadd mysql
    [root@ecs ~]# useradd -s /sbin/nologin -g mysql -M mysql
    [root@ecs ~]# tar -zxvf mysql-5.6.37-linux-glibc2.12-x86_64.tar.gz
    [root@ecs ~]# mv mysql-5.6.37-linux-glibc2.12-x86_64 /usr/local/mysql
    [root@ecs ~]# chown -R mysql:mysql /usr/local/mysql
    [root@ecs ~]# chmod -R 770 /usr/local/mysql
    [root@ecs ~]# chmod -R 777 /tmp
    [root@ecs ~]# yum install -y 'perl(Data::Dumper)' libaio-devel
    [root@ecs ~]# /usr/local/mysql/scripts/mysql_install_db \
    --basedir=/usr/local/mysql \
    --datadir=/usr/local/mysql/data \
    --user=mysql
    [root@ecs ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
    [root@ecs ~]# sed -i "/^basedir=/cbasedir=/usr/local/mysql/" /etc/init.d/mysql
    [root@ecs ~]# sed -i "/^datadir=/cdatadir=/usr/local/mysql/data" /etc/init.d/mysql
    [root@ecs ~]# cp -f /usr/local/mysql/support-files/my-default.cnf /etc/my.cnf
    [root@ecs ~]# cat >> /etc/my.cnf << EOF
    user=mysql
    lower_case_table_names=1
    EOF
    [root@ecs ~]# chkconfig mysql on
    [root@ecs ~]# service mysql start
  2. 修改密码

    [root@ecs ~]# [root@ecs ~]# /usr/local/mysql/bin/mysql -uroot \
    -e "grant all privileges on *.* to 'root'@'localhost' identified by 'changeme' with grant option;flush privileges;"
  3. 放行端口

    [root@ecs ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
    [root@ecs ~]# firewall-cmd --reload

mysql 5.7.31

  1. 安装mysql

    [root@ecs ~]# sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
    [root@ecs ~]# setenforce 0
    [root@ecs ~]# groupadd mysql
    [root@ecs ~]# useradd -s /sbin/nologin -g mysql -M mysql
    [root@ecs ~]# cd /usr/local/src
    [root@ecs ~]# wget -c https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz -P /usr/local/src --progress=bar
    [root@ecs ~]# tar -zxvf mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz
    [root@ecs ~]# mv mysql-5.7.31-linux-glibc2.12-x86_64 /usr/local/mysql
    [root@ecs ~]# mkdir -p /usr/local/mysql/log
    [root@ecs ~]# chown -R mysql:mysql /usr/local/mysql
    [root@ecs ~]# chmod -R 770 /usr/local/mysql
    [root@ecs ~]# chmod -R 777 /tmp
    [root@ecs ~]# yum install -y libaio-devel
    [root@ecs ~]# /usr/local/mysql/bin/mysqld \
    --initialize-insecure \
    --user=mysql \
    --basedir=/usr/local/mysql \
    --datadir=/usr/local/mysql/data \
    --explicit_defaults_for_timestamp=1
    [root@ecs ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
    [root@ecs ~]# sed -i "/^basedir=/cbasedir=/usr/local/mysql" /etc/init.d/mysqld
    [root@ecs ~]# sed -i "/^datadir=/cdatadir=/usr/local/mysql/data" /etc/init.d/mysqld
    [root@ecs ~]# sed -i "/^datadir=/cdatadir=/usr/local/mysql/data" /etc/my.cnf
    [root@ecs ~]# sed -i "/^socket=/csocket=/tmp/mysql.sock" /etc/my.cnf
    [root@ecs ~]# sed -i "/^log-error=/clog-error=/usr/local/mysql/data/mysql.err" /etc/my.cnf
    [root@ecs ~]# sed -i "/^pid-file=/cpid-file=/usr/local/mysql/data/mysql.pid" /etc/my.cnf
    [root@ecs ~]# sed -i "/^\[mysqld\]$/a\lower_case_table_names=1" /etc/my.cnf
    [root@ecs ~]# systemctl enable --now mysqld
  2. 放行端口

    [root@ecs ~]# firewall-cmd --zone=public --add-port=3306/tcp --permanent
    [root@ecs ~]# firewall-cmd --reload

mysql 8.0.19源码安装

  1. 创建my.cnf

    [root@ecs ~]# cat > /etc/my.cnf << EOF
    [mysql]
    default-character-set=utf8mb4
    
    [mysqld]
    socket=/tmp/mysql.sock
    port=3306
    basedir=/usr/local/mysql
    datadir=/usr/local/mysql/data
    max_connections=200
    character_set_server=utf8mb4
    default_storage_engine=INNODB
    lower_case_table_names=1
    log_timestamps=SYSTEM
    default_time_zone='+8:00'
    default_authentication_plugin=mysql_native_password
    
    server_id=1
    log_bin=/usr/local/mysql/log/bin
    log_bin_index=/usr/local/mysql/log/bin.index
    
    [mysqld_safe]
    log_error=/usr/local/mysql/data/mysql.log
    pid_file=/usr/local/mysql/data/mysql.pid
    EOF
  2. 安装mysql

    [root@ecs ~]# sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
    [root@ecs ~]# setenforce 0
    [root@ecs ~]# groupadd mysql
    [root@ecs ~]# useradd -s /sbin/nologin -g mysql -M mysql
    [root@ecs ~]# tar -Jxvf mysql-8.0.19-linux-glibc2.12-x86_64.tar.xz
    [root@ecs ~]# mv mysql-8.0.19-linux-glibc2.12-x86_64 /usr/local/mysql
    [root@ecs ~]# mkdir -p /usr/local/mysql/log
    [root@ecs ~]# chown -R mysql:mysql /usr/local/mysql
    [root@ecs ~]# chmod -R 770 /usr/local/mysql
    [root@ecs ~]# chmod -R 777 /tmp
    [root@ecs ~]# yum install -y libaio-devel
    [root@ecs ~]# /usr/local/mysql/bin/mysqld \
    --defaults-file=/etc/my.cnf \
    --basedir=/usr/local/mysql \
    --datadir=/usr/local/mysql/data \
    --user=mysql --initialize-insecure
    [root@ecs ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
    [root@ecs ~]# systemctl enable --now mysqld
    [root@ecs ~]# firewall-cmd --zone=public --add-port=3306/tcp --permanent
    [root@ecs ~]# firewall-cmd --reload

    --initialize-insecure初始化空密码,否则会生成随机密码。

mysql 8.0.19 rpm安装

  1. 安装mysql

    [root@ecs ~]# tar -xvf mysql-8.0.19-1.el7.x86_64.rpm-bundle.tar
    [root@ecs ~]# rpm -ivh mysql-community-common-8.0.19-1.el7.x86_64.rpm
    [root@ecs ~]# yum remove -y mysql-libs
    [root@ecs ~]# rpm -ivh mysql-community-libs-8.0.19-1.el7.x86_64.rpm
    [root@ecs ~]# rpm -ivh mysql-community-client-8.0.19-1.el7.x86_64.rpm
    [root@ecs ~]# yum install -y libaio-devel
    [root@ecs ~]# rpm -ivh mysql-community-server-8.0.19-1.el7.x86_64.rpm
    [root@ecs ~]# rpm -qa | grep mysql
    [root@ecs ~]# mysqld --initialize
    [root@ecs ~]# chown -R mysql:mysql /var/lib/mysql
    [root@ecs ~]# systemctl start mysqld.service
    [root@ecs ~]# systemctl enable mysqld
  2. 查看初始密码

    [root@ecs ~]# cat /var/log/mysqld.log | grep password

Docker

mysql 5.6

  1. 创建配置文件

    [root@ecs ~]# mkdir -p /data/mysql/{data,etc}
    [root@ecs ~]# cat > data/mysql/etc/my.cnf << EOF
    [mysqld]
    lower_case_table_names=1
    basedir=/usr/
    datadir=/var/lib/mysql/
    socket=/tmp/mysql.sock
    character_set_server=utf8mb4
    collation_server=utf8mb4_general_ci
    sql_mode=ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    
    [mysql]
    default-character-set=utf8mb4
    EOF
  2. 创建容器

    [root@ecs ~]# docker run -d --name mysql \
    --privileged=true \
    -e MYSQL_ROOT_PASSWORD=root \
    -e MYSQL_DATABASE=maisi_db \
    -e MYSQL_USER=maisi \
    -e MYSQL_PASSWORD=123456789 \
    -p 3306:3306 \
    -v /data/mysql/etc/my.cnf:/etc/my.cnf \
    -v /data/mysql/data:/var/lib/mysql \
    maisi/mysql:5.7
  3. 登录测试

    [root@ecs ~]# docker exec -it mysql mysql -u root -p

mysql 8.0

  1. 创建配置文件

    [root@ecs ~]# mkdir -p /data/mysql/{data,etc}
    [root@ecs ~]# cat > /data/mysql/etc/my.cnf << EOF
    [mysql]
    default-character-set=utf8mb4
    
    [mysqld]
    lower_case_table_names=1
    basedir=/usr/
    datadir=/var/lib/mysql/
    socket=/tmp/mysql.sock
    default_authentication_plugin=mysql_native_password
    EOF
  2. 创建容器

    [root@ecs ~]# docker run -d --name mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    -p 3306:3306 \
    -v /data/mysql/etc/my.cnf:/etc/my.cnf \
    -v /data/mysql/data:/var/lib/mysql \
    maisi/mysql:8.0
  3. 查看版本

    [root@ecs ~]# docker exec -it mysql mysql --version
    mysql  Ver 8.0.42 for Linux on x86_64 (MySQL Community Server - GPL)
    [root@ecs ~]# docker exec -it mysql mysql -uroot -p -e "select version();"
    +-----------+
    | version() |
    +-----------+
    | 8.0.42    |
    +-----------+

Ubuntu

  1. 安装mysql

    root@ecs:~# cd /usr/local/src && tar -zxvf mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz
    root@ecs:/usr/local/src# mv mysql-5.7.28-linux-glibc2.12-x86_64 /usr/local/mysql
    root@ecs:/usr/local/src# groupadd mysql
    root@ecs:/usr/local/src# useradd -s /sbin/nologin mysql -g mysql
    root@ecs:/usr/local/src# chown -R mysql:mysql /usr/local/mysql
    root@ecs:/usr/local/src# chmod -R 770 /usr/local/mysql
    root@ecs:/usr/local/src# chmod -R 777 /tmp
    root@ecs:/usr/local/src# ln -s /usr/lib/x86_64-linux-gnu/libncurses.so.6 /usr/lib/x86_64-linux-gnu/libncurses.so.5
    root@ecs:/usr/local/src# ln -s /usr/lib/x86_64-linux-gnu/libtinfo.so.6 /usr/lib/x86_64-linux-gnu/libtinfo.so.5
    root@ecs:/usr/local/src# /usr/local/mysql/bin/mysqld --initialize-insecure \
    --user=mysql \
    --basedir=/usr/local/mysql \
    --datadir=/usr/local/mysql/data \
    --explicit_defaults_for_timestamp=1
    
    [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.

    常见报错:

    • /usr/local/mysql/bin/mysql: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
      解决方法:ln -s /usr/lib/x86_64-linux-gnu/libncurses.so.6 /usr/lib/x86_64-linux-gnu/libncurses.so.5
    • /usr/local/mysql/bin/mysql: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory
      解决方法:ln -s /usr/lib/x86_64-linux-gnu/libtinfo.so.6 /usr/lib/x86_64-linux-gnu/libtinfo.so.5
****查看配置文件路径**

~~~shell
root@ecs:~# /usr/local/mysql/bin/mysql --help | grep "my.cnf"
~~~
  1. 配置my.cnf

    root@ecs:~# cat > /etc/my.cnf <<EOF
    [mysqld]
    lower_case_table_names=1
    datadir=/usr/local/mysql/data
    socket=/tmp/mysql.sock
    
    [mysqld_safe]
    log-error=/usr/local/mysql/log/mysql.log
    pid-file=/usr/local/mysql/data/mysql.pid
    
    !includedir /etc/my.cnf.d
    EOF
    root@ecs:~# mkdir /etc/my.cnf.d
  2. 配置服务

    root@ecs:~# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
    root@ecs:~# sed -i "/^basedir=/cbasedir=/usr/local/mysql" /etc/init.d/mysql
    root@ecs:~# sed -i "/^datadir=/cdatadir=/usr/local/mysql/data" /etc/init.d/mysql
    root@ecs:~# mkdir -p /usr/local/mysql/log
    root@ecs:~# touch /usr/local/mysql/log/mysql.log
    root@ecs:~# chown -R mysql:mysql /usr/local/mysql/log

    启动服务

    root@ecs:~# /etc/init.d/mysql start

    或者:

    root@ecs:~# service mysql start
    root@ecs:~# systemctl enable --now mysql

参数配置

参数说明
character_set_server服务器级别字符集设置,没有明确指定字符集的情况下,数据库、表和列所使用的默认字符集
default_character_set创建数据库的默认字符集
default_character_setdefault-character-set等效
server_id=1集群内mysql服务器id,设置log_bin后必须设置server_id,否则无法启动mysql
log_bin开启Binlog并指定日志存放目录
log_bin_index指定Binlog索引存放目录
expire_logs_daysBinlog过期清理时间(天)
binlog_formatBinlog日志模式
binlog_do_db设置收集日志的数据库,不设置则收集全部数据库
binlog_ignore‌_db设置忽略收集日志的数据库
max_binlog_size单个日志最大文件大小
binlog_cache_sizeBinlog缓存大小,事务大于缓存大小,则使用磁盘
max_binlog_cache_size最大Binlog缓存大小,事务大于最大缓存大小,则事务失败
skip_name_resolve默认值:OFF,ON表示禁止DNS解析,这样连接服务器的客户端的主机名必须和mysql.user表中授权的主机名一致,否则将无法连接
主机名授权的优点:如果一个客户端的IP地址经常变化,那么基于IP的授权将会很繁琐,而客户端的主机名一般是不会变化的,因此基于主机名的授权只须授权一次。

操作

  • 登录数据库

    [root@ecs ~]# mysql -uroot -p
  • 查看配置信息

    [root@ecs ~]# show variables like '%character%';
    +--------------------------+----------------------------------+
    | Variable_name            | Value                            |
    +--------------------------+----------------------------------+
    | character_set_client     | utf8                             |
    | character_set_connection | utf8                             |
    | character_set_database   | latin1                           |
    | character_set_filesystem | binary                           |
    | character_set_results    | utf8                             |
    | character_set_server     | latin1                           |
    | character_set_system     | utf8                             |
    | character_sets_dir       | /usr/local/mysql/share/charsets/ |
    +--------------------------+----------------------------------+
    8 rows in set (0.01 sec)
  • 创建数据库

    mysql> create database maisi_db character set utf8mb4;
  • 修改数据库编码

    mysql> alter database maisi_db character set utf8mb4;

    查看数据库编码

    mysql> show variables like 'character_set_database';
  • 创建用户

    mysql> create user 'maisi'@'%' identified by 'XGu0ZWNSLGcp3nmu';
    mysql> grant select,insert,update,delete,create,drop,index,alter on maisi_db.* to 'maisi'@'%' identified by 'XGu0ZWNSLGcp3nmu';
    mysql> flush privileges;

    删除用户

    mysql> drop user maisi;
  • 修改表编码

    mysql> alter table app_user character set utf8mb4;
  • 修改字段编码

    mysql> alter table app_user change username username varchar(20) character set utf8mb4 not null;
  • 导入数据

    mysql> use maisi_db;
    mysql> source /data/maisi_db.sql;
  • 修改root密码

    Mysql初始化时如果没有使用--initialize-insecure,初始化会生成一个随机root密码,默认root密码是处于过期状态的,因此必须修改密码后才能正常使用,否则会报错:ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

    修改密码的方法较多,支持的方法任选其一:

    方法1(仅适用于mysql 8.0以下版本):

    [root@ecs ~]# /usr/local/mysql/bin/mysql -uroot -e "grant all privileges on *.* to 'root'@'localhost' identified by 'changeme' with grant option;flush privileges;"

    或者:

    [root@ecs ~]# mysql -uroot -h 127.0.0.1 -p
    mysql> grant all privileges on *.* to 'root'@'localhost' identified by 'changeme' with grant option;
    mysql> flush privileges;

    注:

    • 如果开启过远程登录,须将localhost修改为%
    • changeme须修改为实际root密码。
    • mysql 8.0及之后版本不再支持grant授权时创建用户,必须分步操作,先创建用户再进行授权,参考方法7。

    方法2:

    mysql> set password=password('changeme');
    mysql> flush privileges;
    • 即使不用password函数,效果也是一样的。set password='changeme'set password=password('changeme');等效。
    • mysql 8.0及之后版本不再支持password函数,直接使用set password='changeme'

    方法3(仅适用于mysql 5.6及以下版本):

    mysql> update mysql.user set password=password('changeme') where user='root';
    mysql> flush privileges;

    方法4(仅适用于mysql 5.7版本):

    mysql> update mysql.user set authentication_string=password('changeme') where user='root';
    mysql> flush privileges;
    • mysql 5.7开始存储密码的字段由password改为authentication_string,mysql 8.0开始不再支持password函数,因此此方法仅适用于mysql 5.7版。
    • mysql 8.0+不支持password函数,只能设置authentication_string=''空密码。

    方法5(适用于mysql 5.7及以上版本):

    mysql> alter user 'root'@'localhost' identified by 'changeme';

    或者:

    mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'changeme';

    如果修改当前登录用户,可以使用user()替换'root'@'localhost'

    方法6:

    [root@ecs ~]# mysqladmin -uroot -pchangeme password "changeme"

    方法7(仅适用于mysql 8.0及以后版本):

    mysql> create user 'root'@'%' identified by 'changeme';
    mysql> grant all privileges on *.* to 'root'@'%' with grant option;
    mysql> alter user 'root'@'%' identified with mysql_native_password by 'changeme';
    mysql> flush privileges;

    注:

    • grant all privileges on等效grant all on
    • with grant option允许用户将其拥有的权限授予给其他用户,因此必须添加,否则新增的root用户无法给其他用户授权;
    • create user默认使用caching_sha2_password身份认证,客户端如果不支持caching_sha2_password,可以修改成mysql_native_password;
    • mysql 8.0及之后版本create usergrant必须分步操作,mysql 8.0之前创建用户、设置密码、授权可以使用grant一步到位。
  • 开启远程登录

    mysql> update mysql.user set host='%' where user='root';
    mysql> flush privileges;
  • 设置密码有效期

    MySQL自5.6.6版开始,添加了password_expired功能,可以用来设置用户密码是否过期。账户密码过期后,用户可以登录到mysql服务器,但是不能执行任何命令,修改密码后才可执行账户权限内的所有命令。这个特性添加在mysql.user表的password_expired字段(默认值:N)。

    mysql> alter user user() identified with mysql_native_password by 'changeme' password expire interval 180 day failed_login_attempts 3 password_lock_time 2;

    密码有效期180天,启用登录失败跟踪(连续3次输入错误密码则锁定账户2天)

    MySQL自5.7.4版开始,可以通过全局变量default_password_lifetime(单位:天)来设置密码过期策略,MySQL会从启动时开始计算所有用户的密码过期时间。

    [mysqld]
    default_password_lifetime=120

    设置密码永不过期

    mysql> alter user 'root'@'localhost' password expire never;

    强制密码立即失效

    mysql> alter user 'root'@'localhost' password expire;
  • 无授权登录

    mysql 8.0之前版本,在配置文件中添加skip_grant_tables

    [mysqld]
    skip_grant_tables

    mysql 8.0及之后版本,不再支持配置文件skip_grant_tables项,须使用--skip-grant-tables参数启动mysql服务:

    [root@ecs ~]# mysqld --console --skip-grant-tables --shared-memory

    打开新会话窗口登录:

    [root@ecs ~]# mysql -uroot -p

常见报错

1251 - Client does not support authentication protocol reuqested by server; consider upgrading MySQL client

mysql 8.0.11之后使用caching_sha2_password插件进行身份验证,而一些低版本客户端不支持caching_sha2_password,依旧使用的是mysql_native_password插件进行身份验证,因此验证失败。

解决方式:升级客户端,使其支持caching_sha2_password,或者将mysql的用户密码加密规则改为mysql_native_password。

方法1:指定mysql_native_password认证插件设置密码(推荐)

mysql> alter user 'root'@'%' identified with mysql_native_password by 'changeme';
mysql> flush privileges;

方法2:手动更新身份认证插件

  • 查看授权信息

    mysql> select host,user,authentication_string,plugin from mysql.user;
    +-----------+------------------+------------------------------------------------------------------------+-----------------------+
    | host      | user             | authentication_string                                                  | plugin                |
    +-----------+------------------+------------------------------------------------------------------------+-----------------------+
    | %         | root             | $A$005$HYFpxsnfU[n|"&yh48JKDV..KTNA/H55wuaICzsXLRGYQr2/gybGCdV1i5 | caching_sha2_password |
    | localhost | mysql.infoschema | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | caching_sha2_password |
    | localhost | mysql.session    | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | caching_sha2_password |
    | localhost | mysql.sys        | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | caching_sha2_password |
    YEq0QvCJD2A2pT3oubzhEVlDAoZ549WM0hjVds4zZKK/ | caching_sha2_password |
    +-----------+------------------+------------------------------------------------------------------------+-----------------------+
  • 更换验证插件

    mysql> update mysql.user set plugin='mysql_native_password' where user='root';
    mysql> update mysql.user set authentication_string='' where user='root';
    mysql> flush privileges;
    mysql> alter user user() identified by 'changeme';
    mysql> alter user 'root'@'%' identified by 'changeme';

    mysql 8开始不再支持password函数,因此无法直接给authentication_string设置mysql_native_password加密方式的密文。

    注:

    • 不能直接使用alter user user() identified by 'changeme';
      更新mysql.user表某个用户的plugin为mysql_native_password后,内存中的plugin信息并未变更,执行alter user user() identified by 'changeme';修改密码依旧是caching_sha2_password加密方式;
    • 执行flush privileges;会重新加载权限表(mysql.user、mysql.db等)到内存,此时用户的plugin为mysql_native_password,但authentication_string却是caching_sha2_password密文,导致无法验证,执行alter user user() identified by 'changeme';会报错:ERROR 1396 (HY000): Operation ALTER USER failed for 'root'@'%',因此必须将authentication_string置空以避免验证;
    • alter user user() identified by 'changeme';修改的只是当前会话用户的密码,如果root用户有多个host,必须给所有的root用户都重置一下密码。

ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement

解决方法:

mysql> flush privileges;

ERROR 1396 (HY000): Operation ALTER USER failed for 'root'@'skip-grants host'

解决方法:

mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'changeme';

host不一定是localhost,也有可能是%,必须根据查询后的值来设置。

mysql> select host from mysql.user where user='root';

ERROR 1130 (HY000): Host '::1' is not allowed to connect to this MySQL server

mysql.user中root用户的host默认为localhost,而当前连接的主机名是IPv6的::1,两者不一致,因此拒绝访问。

解决方法:

方法1:开启DNS解析,mysql会解析localhost和::1的IP地址,只要IP地址一致即允许连接。

[mysqld]
skip_name_resolve=OFF

方法2:跳过授权验证,修改host为%。

  1. 修改配置文件

    [mysqld]
    skip_grant_tables
  2. 登录mysql,无需输入密码,直接回车登录:

    [root@ecs ~]# mysql -uroot -p
  3. 修改root用户的host值:

    mysql> update mysql.user set host='%' where user='root';
    mysql> flush privileges;

mariadb-libs is obsoleted by mysql-community-libs-8.0.19-1.el7.x86_64

CentOS 7安装了被废弃的mariadb-libs,需要先卸载mariadb-libs。

[root@ecs ~]# yum remove -y mysql-libs

存储引擎

InnoDB

存储结构

版本frmibdopt
<5.7× 数据默认存在系统表空间ibdata1(包含innodb表元数据、undo日志、修改buffer和双写buffer)
5.7每个库有独立的opt文件存储库的信息(如字符集等)
ibd存储表数据(独立表空间)
8.0××frm被sdi取代,sdi(Serialized Dictionary Information)是指表结构元数据。

mysql5.7以下版本开启独立表空间

my.ini:

innodb_file_per_table=1

查看是否生效:

mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'innodb_data_file_path';
+-----------------------+------------------------+
| Variable_name         | Value                  |
+-----------------------+------------------------+
| innodb_data_file_path | ibdata1:10M:autoextend |
+-----------------------+------------------------+
1 row in set (0.00 sec)

ibdata1

ibdata1是一个用来构建InnoDB系统表空间的文件,这个文件包含了innodb表的元数据、undo日志、修改buffer和双写buffer。随着数据库的使用,ibdata1文件会越来越大,innodb_autoextend_increment选项则指定了该文件每次自动增长的步进,默认是8M。

当在MySQL中对InnoDB表进行更改时,这些更改首先存储在InnoDB日志缓冲区的内存中,然后写入通常称为重做日志(redo logs)的InnoDB日志文件中。

MySQL开启独享表空间后,会为每个Innodb表创建一个.ibd的文件。开启方法:innodb_file_per_table=1,这样业务数据将使用独享表空间,而不用全部写入系统表空间ibdata1。

innodb_data_home_dir指定系统表空间文件存放目录,默认为datadir目录。

innodb_data_file_path配置多个innodb tablespace的文件名及文件大小:
innodb_data_file_path=ibdata1:18M;ibdata2:12M:autoextend,只有最后一个表空间文件可以被指定为:autoextend(自动扩展)。

表空间大小必须与当前文件的实际大小匹配,否则会报错:

InnoDB: Error: data file .\ibdata1 is of a different size
InnoDB: 1152 pages (rounded down to MB)
InnoDB: than specified in the .cnf file 16384 pages!

计算公式:1152(pages) / 64(pages/M) = 18(M)

数据恢复

  1. 删除ibdata1、ib_logfile0和ib_logfile1后,启动mysql;
  2. 新建库,按照需要恢复库中的表名新建表。如果没有表结构,可以使用mysql-utilities工具读取frm文件获取表结构;
  3. 停止mysql服务,把原来表的frm文件覆盖到新建的库,修改my.ini后重启mysql服务:

    [mysqld]
    innodb_force_recovery=6
  4. 删除.ibd文件:

    mysql> use maisi_db;
    mysql> alter table app_user discard tablespace;

    如果提示:Cannot delete or update a parent row: a foreign key constraint fails,则需要先关闭外键约束检查,执行删除.ibd命令后,再开启外键约束检查。

    mysql> set foreign_key_checks=0;
    mysql> alter table app_user discard tablespace;
    mysql> set foreign_key_checks=1;
  5. 停止mysql,将原表的ibd文件拷贝到当前库;
  6. 启动mysql,绑定表结构和表数据:

    mysql> use maisi_db;
    mysql> alter table app_user import tablespace;

自动备份

  1. 创建备份脚本backup.sh

    #!/bin/sh
    
    /usr/local/mysql/bin/mysqldump -umaisi -pXGu0ZWNSLGcp3nmu maisi_db --default-character-set=utf8 --opt --skip-lock-tables > /data/backup/maisi_db_`date +%Y-%m-%d`.sql
    
    find /data/backup/ -name "maisi_db_*" -type f -mtime +7 -exec rm {} \;

    docker部署mysql

    #!/bin/sh
    
    MYSQLDUMP="docker exec mysql /usr/bin/mysqldump"
    $MYSQLDUMP -h127.0.0.1 -u maisi -pXGu0ZWNSLGcp3nmu maisi_db > /data/backup/maisi_db_$(date +%Y-%m-%d).sql
  2. 自动运行

    [root@ecs ~]# echo "0 0 */1 * * root /data/backup/backup.sh" >> /etc/crontab
    [root@ecs ~]# systemctl restart crond

    0 0 */1 * *:表示每天00:00(0分0小时)执行一次。

    或者:

    [root@ecs ~]# cat >> /etc/cron.d/backup << EOF
    SHELL=/bin/bash
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    0 0 */1 * * root /data/backup/backup.sh
    EOF
    [root@ecs ~]# systemctl restart crond

安装

Docker部署

  1. 创建Dockerfile

    FROM maisi/alpine:3.22.2
    
    WORKDIR /var/opt/svn
    EXPOSE 3690
    VOLUME ["/var/opt/svn"]
    RUN echo http://mirrors.aliyun.com/alpine/v3.22/main/ > /etc/apk/repositories && \
        apk update && apk upgrade
    RUN apk add --no-cache subversion==1.14.5-r0 wget==1.25.0-r1
    HEALTHCHECK CMD netstat -ln | grep 3690 || exit 1
    CMD [ "/usr/bin/svnserve", "--daemon", "--foreground", "--root", "/var/opt/svn" ]
  2. 构建镜像并创建容器

    [root@ecs ~]# docker build -t svn-server . < Dockerfile
    [root@ecs ~]# docker run --name svn \
    --privileged=true \
    --restart=unless-stopped \
    -p 3690:3690 \
    -v /data/svn:/var/opt/svn \
    -d svn-server
  3. 防火墙放行

    [root@ecs ~]# firewall-cmd --zone=public --add-port=3690/tcp --permanent
    [root@ecs ~]# firewall-cmd --reload

配置

  1. 创建用户和组

    [root@ecs ~]# cat > /data/svn/authz << EOF
    [groups]
    maisi = alice,bob
    
    [/]
    alice = rw
    
    [maisi:/]
    @maisi = rw
    EOF
    
    [root@ecs ~]# cat > /data/svn/passwd << EOF
    [users]
    alice = 123456789
    EOF
    • [/]:所有仓库
    • [maisi:/]:仅maisi仓库
    • @maisi = rw:maisi组内所有用户拥有读写权限
  2. 创建仓库

    [root@ecs ~]# docker exec -it svn svnadmin create maisi

    每个仓库都有独立的conf/svnserve.conf配置文件,配置文件中指定密码文件(passwd)和授权文件(authz)的路径。

    可以将每个仓库的passwd和authz都指向同一个文件,这样只需要建立一套账号和授权即可。

    配置账号和授权

    [root@ecs ~]# docker exec -it svn /bin/sh -c "cd /var/opt/svn/maisi/conf/ \
    && sed -i '/# anon-access = read/a\anon-access = none' svnserve.conf \
    && sed -i '/# auth-access = write/a\auth-access = write' svnserve.conf \
    && sed -i '/# password-db = passwd/a\password-db = \/var/opt\/svn\/passwd' svnserve.conf \
    && sed -i '/# authz-db = authz/a\authz-db = \/var/opt\/svn\/authz' svnserve.conf \
    && sed -i '/# realm = /a\realm = Maisi Lab' svnserve.conf"

    当多个仓库共用同一个passwd和authz时,可以让这些仓库使用相同的realm(默认值是仓库的UUID)。当客户端检测到相同的realm后,则可以共用保存在客户端的用户名和密码进行认证。

  3. 重启服务

    [root@ecs ~]# docker restart svn

数据

  1. 备份

    [root@ecs ~]# svnadmin dump maisi > /data/svn/backup/maisi.dump
  2. 还原

    [root@ecs ~]# svnadmin load maisi < /data/svn/backup/maisi.dump