需求
项目新增了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
16FROM 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.cnf1
2
3[mysql]
# 添加编码设置
default-character-set=utf8mysqld.cnf
: /etc/mysql/mysql.conf.d/mysqld.cnf1
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内存,降低资源消耗需要长期的各种优化,当硬件环境有限制的时候,代码的问题就会显示出来了。
另外,大杂烩还是微服务,这是个问题