一、Docker 镜像构建

1.1 docker镜像创建方式

docker镜像主要有三种自定义构建方式

① dockerfile :基于源镜像修改配置,似乎用dockerfile生成所需的镜像,用于新业务

② 基于已有镜像容器进行操作,经常用于业务升级、迁移、镜像打包

③ 基于本地模板进行构建(使用较少)

 

1.2 Dcokerfile

Dockerfile是一个Docker镜像的描述文件,其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

dockerfile 用于指示 docker image build 命令自动构建Image的源代码

是纯文本文件

示例:

 docker build -f /path/Dockerfile

为什么要使用Dockerfile

问题:在dockerhub中官方提供很多镜像已经能满足我们的所有服务了,为什么还需要自定义镜像

核心作用:日后用户可以将自己应用打包成镜像,这样就可以让我们应用进行容器运行.还可以对官方镜像做扩展,以打包成我们生产应用的镜像。 

完整镜像的结构图:

Docker 镜像构建与优化_nginx

docker镜像分层(基于AUFS构建):

Docker 镜像位于bootfs之上

每一层镜像的下一层成为父镜像

第一层镜像成为base image(操作系统环境镜像)

容器层(可读可写),在最顶层(writable)

容器层以下都是readonl

contaier 读写层

images (只读)

base image

bootfs + rootfs + aufs (kernel)

2、涉及技术:

① bootfs(boot file system) 内核空间

主要包含bootloader和kernel

bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs

这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs

在linux操作系统中(不同版本的linux发行版本),linux加载bootfs时会将rootfs设置为read-only,系统自检后会将只读改为读写,让我们可以在操作系统中进行操作

② rootfs (root file system) 内核空间

在bootfs之上(base images,例如centos 、ubuntu)

包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件

rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等

小结:为什么docker的centos镜像只有200M多一点

bootfs + rootfs :作用是加载、引导内核程序 + 挂载使用linux 操作系统(centos ubantu)等等一些关键的目录文件,对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs

③ AUFS 与 overlay/overlay2 (docker 高版本)

AUFS是一种联合文件系统。它使用同一个Linux host上的多个目录,逐个堆叠起来,对外呈现出一个统一的文件系统。AUFS使用该特性,实现了Docker镜像的分层

而docker 使用了overlay/overlay2存储驱动来支持分层结构

OverlayFS将单个Linux主机上的两个目录合并成一个目录。这些目录被称为层,统一过程被称为联合挂载

overlay 结构:

overlayfs在linux主机上只有两层,一个目录在下层,用来保存镜像(docker),另外一个目录在上层,用来存储容器信息

1、rootfs    基础镜像

2、lower 下层信息 (为镜像层,容器)

3、upper 上层目录 (容器信息,可写)

4、worker 运行的工作目录(copy-on-write写时复制 -》准备容器环境)

5、mergod “视图层”(容器视图)

 

docker 镜像层次结构小结

① base image :基础镜像

② image:固化了一个标准运行环境,镜像本身的功能-封装一组功能性的文件,通过统一的方式,文件格式提供出来

(只读)

③ container:容器层(读写)

④ docker-server 端

⑤ 呈现给docker-client (视图)

在修改时,若upper层没有,则会将lower层有的文件复制到upper层进行修改并保存结果

Dockerfile的格式

 

两种类型的行

l 以# 开头的注释行

l 由专用“指令(Instruction)”开头的指令行

由Image Builder顺序执行各指令,从而完成Image构建

Docker 镜像构建与优化_nginx_02

1.3镜像的分层

l Dockerfile中的每个指令都会创建一个新的镜像层

l 镜像层将被缓存和复用

l 当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效

l 某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效

l 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件。所以在Dockerfile创建镜像过程中会产生临时容器缓存数据,但是创建完成后临时容器都会被删除。

 

1.4 dockerfile 文件结构

Dockerfile文件时以组指令组成,文件结构分为四部分

① 基础镜像信息

② 维护者信息

③ 镜像操作指令

④ 容器启动时执行指令

二、​​docker​​ build工作原理

    docker build [选项] <上下文路径/URL/->

 docker build 后面的 . 表示当前目录,也是指定上下文的路径

上下文:

Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API ,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。

当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 COPY 指令、ADD 指令等。而 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?

这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

那么为什么会有人误以为是指定 Dockerfile 所在目录呢?这是因为在默认情况下,如果不额外指定 Dockerfile 的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile。

这只是默认行为,实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用 -f …/Dockerfile 参数指定某个文件作为 Dockerfile。

当然,一般大家习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中。

 

三、 Dockerfile常用指令

Docker 镜像构建与优化_mysql_03Docker 镜像构建与优化_mysql_04

1、构建镜像命令(ps:可在构建镜像时指定资源限制)

示例:

docker build -t nginx:test .  

-t : tag 打标签

-f : 指定dockerfile 目录

.  : 指构建镜像时使用的环境(当前)目录,构建镜像时使用的上下文环境

 

2、Dockfile语法

  Dockerfile的基本指令有十三个,分别是:FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD。下面对这些指令的用法一一说明。

 FROM

  用法:FROM <image>

  说明:第一个指令必须是FROM了,其指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的latest标签,可以出现多次,可以在一个Dockerfile中构建多个镜像。

MAINTAINER

  用法:MAINTAINER <name> <email>

  说明:描述镜像的创建者,名称和邮箱

RUN

  用法:RUN "command" "param1" "param2"

  说明:RUN命令是一个常用的命令,执行完成之后会成为一个新的镜像,这里也是指镜像的分层构建。一句RUN就是一层,也相当于一个版本。这就是之前说的缓存的原理。我们知道docker是镜像层是只读的,所以你如果第一句安装了软件,用完在后面一句删除是不可能的。所以这种情况要在一句RUN命令中完成,可以通过&符号连接多个RUN语句。RUN后面的必须是双引号不能是单引号(没引号貌似也不要紧),command是不会调用shell的,所以也不会继承相应变量,要查看输入RUN "sh" "-c" "echo" "$HOME",而不是RUN "echo" "$HOME"。

 

 CMD

  用法:CMD command param1 param2

  说明:CMD在Dockerfile中只能出现一次有多个,只有最后一个会有效。其作用是在启动容器的时候提供一个默认的命令项。如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令。没提供就会使用构建时的命令。

EXPOSE

  用法:EXPOSE <port> [<port>...]

  说明:告诉Docker服务器容器对外映射的容器端口号,在docker run -p的时候生效。

ENV

  用法:EVN <key> <value> 只能设置一个

       EVN <key>=<value>允许一次设置多个

  说明:设置容器的环境变量,可以让其后面的RUN命令使用,容器运行的时候这个变量也会保留。

ADD

  用法:ADD <src>   <dest>

  说明:复制本机文件或目录或远程文件,添加到指定的容器目录,支持GO的正则模糊匹配。路径是绝对路径,不存在会自动创建。如果源是一个目录,只会复制目录下的内容,目录本身不会复制。ADD命令会将复制的压缩文件夹自动解压,这也是与COPY命令最大的不同。

 COPY

  用法:COPY <src> <dest>

  说明:COPY除了不能自动解压,也不能复制网络文件。其它功能和ADD相同。

ENTRYPOINT

  用法:ENTRYPOINT "command" "param1" "param2"

说明:这个命令和CMD命令一样,唯一的区别是不能被docker run命令的执行命令覆盖,如果要覆盖需要带上选项--entrypoint,如果有多个选项,只有最后一个会生效。

 

VOLUME

  用法:VOLUME ["path"]

  说明:在主机上创建一个挂载,挂载到容器的指定路径。docker run -v命令也能完成这个操作,而且更强大。这个命令不能指定主机的需要挂载到容器的文件夹路径。但docker run -v可以,而且其还可以挂载数据容器。

USER

  用法:USER daemon

  说明:指定运行容器时的用户名或UID,后续的RUN、CMD、ENTRYPOINT也会使用指定的用户运行命令。

WORKDIR

  用法:WORKDIR path

  说明:为RUN、CMD、ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续参数如果是相对路径,则会基于之前的命令指定的路径。如:WORKDIR  /home  WORKDIR test 。最终的路径就是/home/test。path路径也可以是环境变量,比如有环境变量HOME=/home,WORKDIR $HOME/test也就是/home/test。

ONBUILD

  用法:ONBUILD [INSTRUCTION]

  说明:配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。意思就是,这个镜像创建后,如果其它镜像以这个镜像为基础,会先执行这个镜像的ONBUILD命令。

 

 面试题:

CMD 与entrypoint :都是容器启动时要加载的命令

exec 模式 与shell模式

exec: 容器加载时使用的启动的第一个任务进程

shell: 容器加载时使用的第一个bash(/bin/bash /bin/sh /bin/init)

小结:

 如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略。

 如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数。

 如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式。

 

四、镜像构建实验

1、创建nginx镜像

 准备nginx安装包 :nginx-1.20.2.tar.gz   准备centos:7镜像

mkdir /opt/nginx

cd /opt/nginx

将nginx安装包 :nginx-1.20.2.tar.gz放进目录

编写dockerfile文件

Docker 镜像构建与优化_docker_05

 docker build -f Dockerfile -t nginx:00 .  创建镜像

docker images  查看镜像

Docker 镜像构建与优化_docker_06

运行镜像

[root@node2 nginx]# docker run -itd --name nginx-0 -p 82:80 nginx:00

Docker 镜像构建与优化_mysql_07

浏览器访问验证

这边出现个403,这个原因是因为没有index.html文件

Docker 镜像构建与优化_docker_08

之前已暴露html挂载目录,查看容器信息,查看宿主机的挂载目录

Docker inspect 容器ID

Docker 镜像构建与优化_nginx_09

然后到这个目录创建index.html

Docker 镜像构建与优化_nginx_10

再次浏览器查看

Docker 镜像构建与优化_docker_11

验证成功

 

小结: 构建nginx 镜像

① 创建一个对应的目录(mkdir nginx)

② 编写Dockerfile 文件(最简单的方式,nginx部署脚本 放进去 每条命令用RUN 执行,环境变量使用ENV,移动到对应

目录使用workdir,最后使用CMD 进行启动设置)

③ 在nginx目录中上传nginx-1.12.0.tar.gz 软件包 等文件

④ docker build 创建

⑤ docker run 运行容器

⑥ 检验

 

优化:

重新编写dockfile

Docker 镜像构建与优化_mysql_12

Docker 镜像构建与优化_docker_13

⭐⭐⭐⭐优化方案 加分项

① 减少RUN 指令的使用

RUN yum -y update

RUN yum install -y gcc gcc-c++

整合为yum install -y gcc gcc-c++ && yum -y update

② 将执行后的缓存/不用的输出丢入黑洞 (减少缓存)

yum install -y gcc gcc-c++ && yum -y update > /dev/null

③ 多阶段构建

④ 使用更小体积的linux 发行版本

 

选择精简的基础镜像。

选择体积最小的基础镜像可有效降低镜像体积。如:alpine、busybox等。基础镜像并非越小越好,满足需求和扩展性以及开发者使用的熟悉程度才是更重要的因素。

清理镜像构建的中间产物

构建镜像的过程中,当dockerfile的指令执行完成后,删除镜像不需要用的的文件。如使用yum安装组件,最后可使用yum clean all镜像清理不需要的文件或者使用系统rm命令删除不需要的源文件,或者一些压缩包等。

减少镜像的层数

在使用dockerfile构建镜像时,dockerfile中的每一条指令都会生成一个层,因此可以通过合并dockerfile中可合并的指令,减少最终生成镜像的层数。例如:在dockerfile中使用RUN执行shell命令是,可以用"&&"将多条命令连接起来。

充分利用镜像构建缓存

1)利用构建的缓存来加快镜像构建速度,Docker构建默认会开启缓存,缓存生效有三个关键点,镜像父层没有发生变化,构建指令不变,添加文件校验和一致。只要一个构建指令满足这三个条件,这一层镜像构建就不会再执行,它会直接利用之前构建的结果。

2)某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效。我们应该把变化最少的部分放在Dockerfile的前面,这样可以充分利用镜像缓存。

3)dockerfile中有可能导致缓存失效的命令WORKDIR、CMD、ENV、ADD等,像这些命令最好放到dockerfile底部,以便在构建镜像过程中最大限度使用缓存。

优化网络请求

使用一些镜像源或者在dockerfile中使用互联网上的url时,去用一些网络比较好的开源站点,这样可以节约时间、减少失败率。

优化实验

mkdir nginx 
mkdir -p nginx/nginx_v1 nginx/nginx_v2 nginx/nginx_v3

#未优化之前
FROM centos:7
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
#关闭debug日志
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

Docker 镜像构建与优化_nginx_14

docker build -t "nginx:v1" .

#查看镜像大小 docker images

Docker 镜像构建与优化_mysql_15

启动容器 docker run -d -P nginx:v1

Docker 镜像构建与优化_mysql_16

PS 1 : 不要用docker run -d -P nginx:v1 /bin/bash

/bin/bash 指定了shell环境,而我们的dockerfile 已指定CMD,即默认启动时加载的命令/执行程序,使用/bin/bash这种shell环境会覆盖cmd命令,导致容器运行时nginx 不会加载

PS 2: VOLUME 宿主机的挂载点可使用docker insepct 查看

① 默认会放在var/lib/docker/volumes/容器ID/_data中

② 可以使用docker run -d -P -v /data1:/usr/local/nginx/html 来指定

#运行镜像、查看挂载位置

Docker 镜像构建与优化_docker_17

优化1:不需要输出的指令丢入/dev/null (需要确定命令执行的是正确的)

FROM centos:7
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> /dev/null && yum clean all
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
#关闭debug日志
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx &> /dev/null
RUN make &> /dev/null
RUN make install &> /dev/null
RUN rm -rf /mnt/nginx-1.15.9
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx""-g","daemon off;"]

Docker 镜像构建与优化_nginx_18

docker build -t nginx:v2 .

Docker 镜像构建与优化_mysql_19

Docker 镜像构建与优化_mysql_20Docker 镜像构建与优化_nginx_21

#优化2:减少RUN构建

FROM centos:7
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> /dev/null && \
yum clean all && \
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --prefix=/usr/local/nginx &> /dev/null && \
make &> /dev/null && make install &> /dev/null &&\
rm -rf /mnt/nginx-1.15.9
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

Docker 镜像构建与优化_docker_22

docker build -t nginx:v3 .

Docker 镜像构建与优化_mysql_23

Docker 镜像构建与优化_mysql_24

##优化3:多阶段构建(使用FROM命令生成多个镜像,将指定的镜像做为其他镜像的基础镜像环境来构建)

FROM centos:7 as build 
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> /dev/null && \
yum clean all &&\
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --prefix=/usr/local/nginx &> /dev/null && \
make &>/dev/null && \
make install &>/dev/null && \
rm -rf /mnt/nginx-1.15.9

FROM centos:7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY --from=build /usr/local/nginx /usr/local/nginx
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

Docker 镜像构建与优化_mysql_25

[root@docker1 nginx]# docker build -t nginx:v4 .

Docker 镜像构建与优化_nginx_26

Docker 镜像构建与优化_mysql_27

##优化4 使用更为轻量级的linux 发行版本

debian

alpine

2、构建tomcat镜像

mkdir /opt/tomcat

拷贝jdk-8u91-linux-x64.tar.gz 、apache-tomcat-9.0.16.tar.gz 到/opt/tomcat下

Docker 镜像构建与优化_mysql_28

cd /opt/tomcat
vim Dockerfile

FROM centos:7
MAINTAINER this is tomcat image <sss>
ADD jdk-8u91-linux-x64.tar.gz /usr/local
WORKDIR /usr/local/
RUN mv jdk1.8.0_91 /usr/local/java
ENV JAVA_HOME /usr/local/java
ENV JAVA_BIN /usr/local/java/bin
ENV JRE_HOME /usr/local/java/jre
ENV PATH $PATH:/usr/local/java/bin:/usr/local/java/jre/bin
ENV CLASSPATH /usr/local/java/jre/bin:/usr/local/java/lib:/usr/local/java/jre/lib/charsets.jar
ADD apache-tomcat-9.0.16.tar.gz /usr/local
WORKDIR /usr/local/
RUN mv apache-tomcat-9.0.16 /usr/local/tomcat8
EXPOSE 8080
#CMD ["/usr/local/tomcat8/bin/catalina.sh","run"]
ENTRYPOINT ["/usr/local/tomcat8/bin/catalina.sh","run"]

Docker 镜像构建与优化_nginx_29

生成镜像:docker build -t centos:tomcat .

Docker 镜像构建与优化_docker_30

Docker 镜像构建与优化_mysql_31

运行:

Docker 镜像构建与优化_nginx_32

Docker 镜像构建与优化_docker_33

mysql镜像制作​

####dockerfile-mysql

cd /opt

mkdir kiki

cd kiki

mkdir mysql

cd mysql

vim my.cnf

 

[client]

port = 3306

default-character-set=utf8

socket = /usr/local/mysql/mysql.sock

 

[mysql]

port = 3306

default-character-set=utf8

socket = /usr/local/mysql/mysql.sock

 

[mysqld]

user = mysql

basedir=/usr/local/mysql

datadir=/usr/local/mysql/data

port = 3306

character-set-server=utf8

pid-file = /usr/local/mysql/mysqld.pid

socket = /usr/local/mysql/mysql.sock

server-id = 1

 

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES

 

:wq

 

##########上传安装包mysql-boost-5.7.20.tar.gz

 

vim Dockerfile

 

FROM centos:7

 

ADD mysql-boost-5.7.20.tar.gz /usr/local

 

RUN yum -y install \

ncurses \

ncurses-devel \

bison \

cmake \

gcc \

gcc-c++ \

make

 

RUN useradd -M -s /sbin/nologin  mysql

 

WORKDIR /usr/local/mysql-5.7.20/

 

RUN cmake \

-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \

-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \

-DSYSCONFDIR=/etc \

-DSYSTEMD_PID_DIR=/usr/local/mysql \

-DDEFAULT_CHARSET=utf8  \

-DDEFAULT_COLLATION=utf8_general_ci \

-DWITH_EXTRA_CHARSETS=all \

-DWITH_INNOBASE_STORAGE_ENGINE=1 \

-DWITH_ARCHIVE_STORAGE_ENGINE=1 \

-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \

-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \

-DMYSQL_DATADIR=/usr/local/mysql/data \

-DWITH_BOOST=boost \

-DWITH_SYSTEMD=1 && make && make install

 

WORKDIR /opt/kiki/mysql

ADD my.cnf /etc

 

RUN chown -R mysql:mysql /usr/local/mysql/

RUN chown mysql:mysql /etc/my.cnf

 

ENV PATH $PATH:/usr/local/mysql/bin:/usr/local/mysql/lib

 

WORKDIR /usr/local/mysql/

RUN bin/mysqld \

--initialize-insecure \

--user=mysql \

--basedir=/usr/local/mysql \

--datadir=/usr/local/mysql/data

 

RUN cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/

EXPOSE 3306

 

RUN echo -e "#!/bin/sh \nsystemctl enable mysqld" >/run.sh

RUN chmod 755 /run.sh

RUN sh /run.sh

CMD ["init"]

 

docker run --privileged -d -P mysql:v1

 

#进入容器

mysql -uroot -p

 

grant all privileges on *.* to 'root'@'%' identified by '123123';

grant all privileges on *.* to 'root'@'localhost' identified by '123123';

 

创建库、表示

 

#测试

宿主机安装mariadb

yum install -y mariadb

mysql -uroot -P 容器端口 -p123123