--- title: Docker定制镜像 date: 2019-12-03 10:22:09 description: Docker定制镜像,包含Java、Redis、Mysql等服务 categories: [技术总结] tags: [Docker, Java, Redis, MySQL] --- ## 需求 项目新增了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作为基础镜像安装软件非常方便,以后也好扩展 ```dockerfile 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是容器入口脚本,里面可以启动服务,需要注意:前几条是后台启动,最后一条要前台启动,不然容器会自动退出 ```PowerShell #!/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密码,权限,数据库初始化,编码设置等操作 ```PowerShell #!/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 ```yaml [mysql] # 添加编码设置 default-character-set=utf8 ``` `mysqld.cnf`: /etc/mysql/mysql.conf.d/mysqld.cnf ```yaml ... [mysqld] # 去掉host限制 # bind-address = 127.0.0.1 # 添加编码设置 character-set-server=utf8 ... ``` 编码查看语句: ```sql show variables like '%char%'; ``` ### Jenkinsfile 持续集成脚本,先构建jar包,再构建minifund镜像 ```groovy #!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的部署,学习成本较低 ```bash docker run -d -p 8088:8088 -p 7654:3306 --name mini minifund ``` ### 后记 构建好的镜像保证50人正常使用时要占1G内存,降低资源消耗需要长期的各种优化,当硬件环境有限制的时候,代码的问题就会显示出来了。 另外,大杂烩还是微服务,这是个问题