实验背景
直接使用官方MySQL镜像,没有做进一步的安全加固,有时不符合项目中的安全规范,为了更好地控制MySQL的用户uid和目录权限,需要自己使用源码包编译制作特定版本的MySQL docker 镜像。
一、实验环境
虚拟机操作系统: CentOS7.5
docker版本:18.06.0-ce
二、创建工作目录,下载镜像制作所需软件包
# mkdir /root/mysql5.7.28-docker
# cd /root/mysql5.7.28-docker
# wget -O /root/mysql5.7.28-docker/gosu https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64
# chmod +x /root/mysql5.7.28-docker/gosu
# wget http://www.sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
# wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.28.tar.gz
# cat Dockerfile
#############################################################################
FROM centos:centos7.5.1804
COPY mysql-5.7.28.tar.gz /opt
COPY boost_1_59_0.tar.gz /opt
RUN echo "sslverify=0" >> /etc/yum.conf && \
yum clean all && \
rpm --rebuilddb && \
yum -y install gcc gcc-c++ ncurses ncurses-devel make cmake bison bison-devel openssl openssl-devel pwgen zlib zlib-devel && \
cd /opt && \
tar -zxf boost_1_59_0.tar.gz && \
mv boost_1_59_0 /usr/local/ && \
groupadd -g 2020 mysql && \
useradd -r -u 2020 -g mysql -s /sbin/nologin mysql && \
tar -zxf mysql-5.7.28.tar.gz && \
cd mysql-5.7.28 && \
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/var/lib/mysql \
-DSYSCONFDIR=/etc \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=/var/run/mysqld/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DENABLE_DOWNLOADS=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_DEBUG=0 \
-DMYSQL_MAINTAINER_MODE=0 \
-DWITH_BOOST=/usr/local/boost_1_59_0 && \
make -j `grep processor /proc/cpuinfo | wc -l` && \
make install && \
yum -y remove gcc gcc-c++ ncurses-devel make cmake bison-devel openssl-devel zlib-devel && \
yum clean all && \
rm -rvf /opt/* /usr/local/boost_1_59_0 /var/cache/yum/* /usr/lib/gcc && \
mkdir -p /var/lib/mysql /etc/mysql/conf.d && \
mkdir -p /var/run/mysqld /opt/mysql/sec_file && \
chown -R mysql:mysql /usr/local/mysql /var/lib/mysql /etc/mysql /var/run/mysqld && \
chmod 700 /usr/local/mysql /var/lib/mysql /etc/mysql /var/run/mysqld && \
chmod 000 /opt/mysql/sec_file && \
chmod 500 /usr/local/mysql/bin/* && \
find /usr/local/mysql/lib/plugin/ -type d -exec chmod 500 {} \; && \
find /usr/local/mysql/lib/plugin/ -type f -name "*.so" -exec chmod 400 {} \; && \
rm -rvf /usr/local/mysql/bin/myisam* && \
rm -rvf /usr/local/mysql/bin/mysql_config* && \
rm -rvf /usr/local/mysql/bin/mysqlcheck && \
rm -rvf /usr/local/mysql/bin/mysqlshow && \
rm -rvf /usr/local/mysql/bin/mysqlslap && \
rm -rvf /usr/local/mysql/bin/mysqlxtest && \
rm -rvf /usr/local/mysql/mysql-test && \
rm -rvf /usr/local/mysql/share/*.sql
COPY docker-entrypoint.sh /
COPY my.cnf /etc/mysql
COPY gosu /usr/local/bin/
RUN chown -R mysql:mysql /etc/mysql /docker-entrypoint.sh && \
chmod 700 /docker-entrypoint.sh /usr/local/bin/gosu && \
chmod 600 /etc/mysql/my.cnf
VOLUME /var/lib/mysql
ENV PATH=/usr/local/mysql/bin:$PATH
ENV UMASK=384
ENV UMASK_DIR=448
ENV MYSQL_HISTFILE=/dev/null
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
#############################################################################
# cat docker-entrypoint.sh
############################################################
#!/bin/sh
set -e
umask 0077
if [ -z "$(ls -A /var/lib/mysql)" ]; then
if [ -z "${MYSQL_ROOT_PASSWORD}" ]; then
mysqld --initialize-insecure --user=mysql
else
mysqld --initialize-insecure --user=mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
/etc/init.d/mysqld start
mysql -u root --skip-password -e "alter user root@'localhost' identified by \"${MYSQL_ROOT_PASSWORD}\";"
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "flush privileges;"
/etc/init.d/mysqld stop
rm -f /etc/init.d/mysqld
fi
fi
exec gosu mysql "$@"
############################################################
# chmod +x docker-entrypoint.sh
在MySQL数据目录为空、允许以非安全模式(root@'localhost'为空密码)初始化:
1. 如果MYSQL_ROOT_PASSWORD为空值,直接以非安全模式(root空密码)初始化
2. 如果MYSQL_ROOT_PASSWORD不为空值,以非安全模式初始化,然后根据MYSQL_ROOT_PASSWORD的传值,设置root@'localhost'的密码
三、用Dockerfile文件build镜像
# docker build -f Dockerfile -t mysql:5.7.28 .
# docker images
可以看出,应该说,跟官方镜像比,体积确实大了不少!
四、用镜像起容器测试
初始化MySQL
# cat mysql5.7.28_test.sh
#########################################################
#!/bin/bash
mysql_ver="5.7.28"
mysql_datadir="/opt/mysqldata"
mysql_root_pwd="MySQL@123"
registry_addr=""
docker run -itd \
--name mysql \
-p 3306:3306 \
-e MYSQL_HISTFILE=/dev/null \
-v ${mysql_datadir}:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD="${mysql_root_pwd}" \
mysql:${mysql_ver}
sleep 30
if ss -tan | grep -w "3306" > /dev/null 2>&1; then
echo "Mysql init successfuly!"
else
echo "Mysql init failed!"
fi
##########################################################
# mkdir /opt/mysqldata
# sh mysql5.7.28_test.sh
# chmod 400 /opt/mysqldata/*.pem
# docker exec -it mysql mysql -u root -p"MySQL@123"
# docker exec -it mysql mysql -u root -p"MySQL@123" -e "select user,host from mysql.user;"
开启root远程登录
# docker exec -it mysql mysql -u root -p"MySQL@123" -e "grant all privileges on *.* to root@'%' identified by 'MySQL@123' with grant option;"
# docker exec -it mysql mysql -u root -p"MySQL@123" -e "flush privileges;"
# docker exec -it mysql mysql -u root -p"MySQL@123" -e "select user,host from mysql.user;"
# docker exec -it mysql cat /etc/passwd
# docker exec -it mysql ls -l /usr/local/mysql
五、将容器服务注册成系统服务
# docker stop mysql
# docker rm mysql
# mkdir /opt/mysqlconfig
# cat /opt/mysqlconfig/my.cnf
###################################################
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysql.sock
datadir = /var/lib/mysql
secure-file-priv = /opt/mysql/sec_file
symbolic-links = 0
max_connections = 1000
skip_name_resolve
character-set-client-handshake = FALSE
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,STRICT_ALL_TABLES"
character-set-server = utf8
collation-server = utf8_general_ci
init_connect = "SET NAMES 'utf8'"
[mysql]
default-character-set = utf8
[client]
default-character-set = utf8
###################################################
# chown -R 2020:2020 /opt/mysqlconfig
# cat /etc/systemd/system/mysqld.service
#####################################################
[Unit]
Description=MySQL Server
After=network-online.target docker.service
Requires=docker.service
[Service]
ExecStartPre=-/usr/bin/docker rm -f mysql
ExecStart=/usr/bin/docker run \
--name mysql \
-p 3306:3306 \
-e UMASK=0600 \
-e UMASK_DIR=0700 \
-e MYSQL_HISTFILE=/dev/null \
-v /opt/mysqldata:/var/lib/mysql \
-v /opt/mysqlconfig/mysqld.cnf:/etc/mysql/my.cnf \
mysql:5.7.28
ExecStop=/usr/bin/docker stop mysql
LimitNOFILE=65535
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
#####################################################
# systemctl daemon-reload
# systemctl start mysqld.service
# systemctl enable mysqld.service
# systemctl status mysqld.service
# docker exec -it mysql ps aux
# docker exec -it mysql env
六、参考
【MySQL&docker】基于CentOS7.5 编译制作MySQL5.7.28镜像
https://www.jianshu.com/p/71fd79b69a6b
MySQL5.7 导入数据提示--secure-file-priv选项报错解决
https://blog.51cto.com/hld1992/2368512
https://www.cnblogs.com/Braveliu/p/10728162.html
MySQL UMASK或UMASK_DIR环境变量
https://www.docs4dev.com/docs/zh/mysql/5.7/reference/file-permissions.html
How to solve InnoDB: Unable to lock ./ibdata1 mysql error?
https://stackoverflow.com/questions/35978228/how-to-solve-innodb-unable-to-lock-ibdata1-mysql-error