Docker定制镜像

需求

项目新增了redis相关的依赖后,变的越来越庞大,部署也很麻烦了,CTO想把这些环境都打包到一个镜像中去做一个mini版本,用于测试和客户的临时试用。
这样做似乎违背了Docker一个容器内只有一个主进程的设计原则,但是能让初学者低门槛使用镜像,也是有些作用的。

文件结构

  • Dockerfile :镜像构建脚本,环境安装和初始化,只运行一次
  • docker-entrypoint.sh :容器入口脚本,开启服务,每次启动容器都会运行
  • mysql-init.sh :MySQL初始化脚本,在构建镜像时调用
  • mysql.cnf mysqld.cnf :MySQL配置文件
  • schema.sql data.sql :MySQL初始化sql文件,表结构和预置数据
  • Jenkinsfile :持续集成脚本

Dockerfile

选择Ubuntu作为基础镜像安装软件非常方便,以后也好扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FROM ubuntu:18.04
RUN apt-get update && \
apt-get install -y redis-server \
openjdk-8-jdk \
mysql-server \
mysql-client
ADD miniFund/docker-entrypoint.sh /docker-entrypoint.sh
ADD miniFund/mysql-init.sh /mysql-init.sh
ADD miniFund/mysql.cnf /etc/mysql/conf.d/mysql.cnf
ADD miniFund/mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf
ADD src/main/resources/db/migration/V1.0__schema.sql schema.sql
ADD src/main/resources/db/migration/V1.1__import_presetTable_data.sql data.sql
ADD target/efi-1.0.jar app.jar
RUN chmod 777 /docker-entrypoint.sh && chmod 777 /mysql-init.sh
RUN ["/bin/bash", "-c", "/mysql-init.sh"]
ENTRYPOINT ["/docker-entrypoint.sh"]

docker-entrypoint.sh

docker-entrypoint.sh是容器入口脚本,里面可以启动服务,需要注意:前几条是后台启动,最后一条要前台启动,不然容器会自动退出

1
2
3
4
5
6
7
#!/bin/bash
# 启动mysql
/etc/init.d/mysql start
# 启动redis
redis-server &
# 启动java
java -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=mini -jar /app.jar

mysql-init.sh

mysql-init.sh是MySQL初始化脚本,包括设置root密码,权限,数据库初始化,编码设置等操作

1
2
3
4
5
6
7
8
#!/bin/bash
## mysql初始化脚本
/etc/init.d/mysql start
mysql <<<"CREATE DATABASE IF NOT EXISTS efi CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';"
mysql efi < schema.sql
mysql efi < data.sql
mysql <<<"update mysql.user set authentication_string=PASSWORD('123456'), plugin='mysql_native_password', host='%' where user='root';flush privileges;"
/etc/init.d/mysql restart

  • 这里的root密码设置的很简单,host也设置成了%,是为了跑压力测试软件用的,如果是给客户试用就不用开MySQL访问权限了。
  • 主要解决问题:权限、编码、交互式脚本
  • schema.sql是表结构,data.sql是预置数据

MySQL配置文件

mysql.cnf: /etc/mysql/conf.d/mysql.cnf

1
2
3
[mysql]
# 添加编码设置
default-character-set=utf8

mysqld.cnf: /etc/mysql/mysql.conf.d/mysqld.cnf
1
2
3
4
5
6
7
...
[mysqld]
# 去掉host限制
# bind-address = 127.0.0.1
# 添加编码设置
character-set-server=utf8
...

编码查看语句:
1
show variables like '%char%';

Jenkinsfile

持续集成脚本,先构建jar包,再构建minifund镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!groovy
pipeline {
agent none
stages {
stage('Build') {
agent {
docker {
image 'maven:3.5.0-jdk-8-alpine'
args '-v mavenRepository:/root/.m2 -e TZ=Asia/Shanghai'
}
}
steps {
sh 'mvn -B -DskipTests clean package --settings settings.xml'
}
}
stage('Deliver') {
agent any
steps {
sh 'docker build -f miniFund/Dockerfile -t minifund .'
}
}
}
}

容器使用

按上面的脚本构建出的minifund镜像,直接启动就有一个完整的后端环境了,使用者不用关心redis和mysql的部署,学习成本较低

1
docker run -d -p 8088:8088 -p 7654:3306 --name mini minifund

后记

构建好的镜像保证50人正常使用时要占1G内存,降低资源消耗需要长期的各种优化,当硬件环境有限制的时候,代码的问题就会显示出来了。
另外,大杂烩还是微服务,这是个问题

文章目录
  1. 1. 需求
    1. 1.1. 文件结构
    2. 1.2. Dockerfile
    3. 1.3. docker-entrypoint.sh
    4. 1.4. mysql-init.sh
    5. 1.5. MySQL配置文件
    6. 1.6. Jenkinsfile
    7. 1.7. 容器使用
    8. 1.8. 后记