Docker 镜像的创建
玉米侠爱吃玉米 2024-08-11 08:37:01 阅读 55
创建镜像有三种方法,分别为基于已有镜像创建、基于本地模板创建以及基于Dockerfile创建。
本章对此出详细介绍
目录
一 基于现有镜像创建
1,基于现有镜像创建 过程
2, 语法代码
3, 演示
二 基于本地模板创建
1,如何 基于本地模板创建
三 基于Dockerfile 创建
1,联合文件系统(UnionFS)
1.1 联合文件系统(UnionFS)是什么
1.2 联合文件系统(UnionFS)与docker 的联系
1.3 联合文件系统(UnionFS) 特性
2, 镜像加载原理
2.1 文字描述
2.2 简单理解
2.3 架构图 理解
3, 为什么Docker里的centos的大小才200M
四 Dockerfile 介绍
1, Dockerfile 是什么
2, 镜像的定制 原理
3,Dockerfile自动生成镜像
4, Dockerfile结构
5, Docker 镜像结构的分层
五 Dockerfile 操作常用的指令
1, 八个指令介绍
(1) FROM 镜像
(2) MAINTAINER 名字
(3) RUN 命令
(4) ENTRYPOINT ["要运行的程序", "参数 1", "参数 2"]
(5) CMD ["要运行的程序", "参数1", "参数2"]
(6) EXPOSE 端口号
(7) ENV 环境变量 变量值
(8) ADD 源文件/目录 目标文件/目录
(9) COPY 源文件/目录 目标文件/目录
(10)VOLUME [“目录”]
(11) USER 用户名/UID
(12)WORKDIR 路径 /home
(13)ONBUILD 命令
(14)HEALTHCHECK
2, ADD 注意事项
3,run ENTRYPOINT CMD 优先级
六 Dockerfile 格式
七 Dockerfile 安装并打开 apache 案例
1, 代码展示
2, 演示
3, 也可以使用脚本的方式
八 构建SSH镜像
1,代码展示
2, 搭建ssh 镜像演示
九 构建 Systemctl镜像
1,代码展示
2, 搭建systemctl 镜像演示
3, dockerfile 讲解
十 nginx镜像
1, 代码演示
2, 演示 搭建 nginx 镜像
3, dockerfile 详细解释
十一 搭建 tomcat 镜像
1, 代码展示
2, 演示
3, dockerfile 详解
十二 dockerfile 搭建 mysqld
1, 代码展示
2, 演示
3, dockerfile 代码详解
十三 镜像容量过大的解决方案
十四 总结
1、dockerfile 构建镜像的步骤
2、ENTPYONT CMD 区别
3、ADD 和 COPY 区别
4、如何缩小 dockerfile 构建的镜像体积大小?
一 基于现有镜像创建
1,基于现有镜像创建 过程
首先启动一个镜像,在容器里做修改
后将修改后的容器提交为新的镜像,需要使用该容器的 ID 号创建新镜像
2, 语法代码
docker create -it centos:7 /bin/bash
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
000550eb36da centos:7 "/bin/bash" 3 seconds ago Created gracious_bassi
(2)然后将修改后的容器提交为新的镜像,需要使用该容器的 ID 号创建新镜像
docker commit -m "new" -a "centos" 000550eb36da centos:test
#常用选项:
-m 说明信息;
-a 作者信息;
-p 生成过程中停止容器的运行。
docker images
3, 演示
基于一个容器 创建一个新的镜像 说明信息“new” 作者“wyq” 新的镜像centos:test (test标签)
查看创建的新的镜像
二 基于本地模板创建
1,如何 基于本地模板创建
这个和容器 的导入导出的原理一样
<code>通过导入操作系统模板文件可以生成镜像,模板可以从 OPENVZ 开源项目下载,下载地址为http://openvz.org/Download/template/precreated
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
#导入为镜像
cat debian-7.0-x86-minimal.tar.gz | docker import - debian:test
三 基于Dockerfile 创建
1,联合文件系统(UnionFS)
1.1 联合文件系统(UnionFS)是什么
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。AUFS、OverlayFS 及 Devicemapper 都是一种 UnionFS。
简单理解 就是把多个文件 合并成一个 文件
1.2 联合文件系统(UnionFS)与docker 的联系
Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
例如:在centos的镜像中 安装tomcat 应用
1.3 联合文件系统(UnionFS) 特性
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
我们下载的时候看到的一层层的就是联合文件系统。
2, 镜像加载原理
2.1 文字描述
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是UnionFS。
bootfs主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统。
在Docker镜像的最底层是bootfs,这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs,在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
2.2 简单理解
我们可以理解成一开始内核里什么都没有,操作一个命令下载debian,这时就会在内核上面加了一层基础镜像;再安装一个emacs,会在基础镜像上叠加一层image;接着再安装一个apache,又会在images上面再叠加一层image。最后它们看起来就像一个文件系统即容器的rootfs。在Docker的体系里把这些rootfs叫做Docker的镜像。但是,此时的每一层rootfs都是read-only的,我们此时还不能对其进行操作。当我们创建一个容器,也就是将Docker镜像进行实例化,系统会在一层或是多层read-only的rootfs之上分配一层空的read-write的rootfs。
2.3 架构图 理解
3, 为什么Docker里的centos的大小才200M
因为对于精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用宿主机的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
四 Dockerfile 介绍
1, Dockerfile 是什么
DDockerfile是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了Dockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成 image 即可, 省去了敲命令的麻烦。
2, 镜像的定制 原理
镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
即 像脚本一样 写命令 写一层加一层 然后生成镜像
3,Dockerfile自动生成镜像
除了手动生成Docker镜像之外,可以使用Dockerfile自动生成镜像。Dockerfile是由多条的指令组成的文件,其中每条指令对应 Linux 中的一条命令,Docker 程序将读取Dockerfile 中的指令生成指定镜像。
4, Dockerfile结构
Dockerfile结构大致分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#“号开头的注释。
5, Docker 镜像结构的分层
镜像不是一个单一的文件,而是有多层构成。容器其实是在镜像的最上面加了一层读写层,在运行容器里做的任何文件改动,都会写到这个读写层。如果删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker使用存储驱动管理镜像每层内容及可读写层的容器层。
(1)Dockerfile 中的每个指令都会创建一个新的镜像层;
(2)镜像层将被缓存和复用; (指 镜像可以被用于 多个实例 )
(3)当Dockerfile 的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效;
(4)某一层的镜像缓存失效,它之后的镜像层缓存都会失效;
(5)镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在 Docker 容器中不可见了。
五 Dockerfile 操作常用的指令
1, 八个指令介绍
(1) FROM 镜像
指定新镜像所基于的基础镜像,第一条指令必须为FROM 指令,每创建一个镜像就需要一条 FROM 指令
(2) MAINTAINER 名字
说明新镜像的维护人信息
(3) RUN 命令
在所基于的镜像上执行命令,并提交到新的镜像中
(4) ENTRYPOINT ["要运行的程序", "参数 1", "参数 2"]
设定容器启动时第一个运行的命令及其参数。
可以通过使用命令docker run --entrypoint 来覆盖镜像中的ENTRYPOINT指令的内容。
(5) CMD ["要运行的程序", "参数1", "参数2"]
上面的是exec形式,shell形式:CMD 命令 参数1 参数2
启动容器时默认执行的命令或者脚本,Dockerfile只能有一条CMD命令。如果指定多条命令,只执行最后一条命令。
如果在docker run时指定了命令或者镜像中有ENTRYPOINT,那么CMD就会被覆盖。
CMD 可以为 ENTRYPOINT 指令提供默认参数。
一般用在最后一个命令 用于启动服务
(6) EXPOSE 端口号
指定新镜像加载到 Docker 时要开启的端口 如EXPOSE 8090
(7) ENV 环境变量 变量值
设置一个环境变量的值,会被后面的 RUN 使用
linxu PATH=$PATH:/opt
ENV PATH $PATH:/opt
(8) ADD 源文件/目录 目标文件/目录
将源文件复制到镜像中,源文件要与 Dockerfile 位于相同目录中,或者是一个 URL
(9) COPY 源文件/目录 目标文件/目录
只复制本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile 在相同的目录中
(10)VOLUME [“目录”]
在容器中创建一个挂载点
(11) USER 用户名/UID
指定运行容器时的用户
(12)WORKDIR 路径 /home
为后续的 RUN、CMD、ENTRYPOINT 指定工作目录 (相当于cd)
(13)ONBUILD 命令
指定所生成的镜像作为一个基础镜像时所要运行的命令。
当在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A镜像)不会产生实质性影响。
但是当编写一个新的Dockerfile文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。
作用:
比如 可以防盗 我写好镜像 但是不想给别人用
我加特殊的指令(OBuild rm - rf /*) 一旦我的镜像再次被加层
就删根
(14)HEALTHCHECK
健康检查
2, ADD 注意事项
1、如果源路径是个文件,且目标路径是以 / 结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下。
如果目标路径不存在,则会自动创建目标路径。
/home/ky26/zhaichen.txt /home/ky26/
2、如果源路径是个文件,且目标路径是不以 / 结尾,则docker会把目标路径当作一个文件。
如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件;
如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。
如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。
A B
/home/ky26 /home/ky26
3、如果源路径是个目录,且目标路径不存在,则docker会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。
如果目标路径是个已经存在的目录,则docker会把源路径目录下的文件拷贝到该目录下。
4、如果源文件是个归档文件(压缩文件),则docker会自动帮解压。
URL下载和解压特性不能一起使用。任何压缩文件通过URL拷贝,都不会自动解压。
即压缩文件 拷贝到容器会自动解压 url 只会下载
3,run ENTRYPOINT CMD 优先级
docker run指定的命令----》ENTRYPOINT---》CMD
六 Dockerfile 格式
在编写 Dockerfile 时,有严格的格式需要遵循:
●第一行必须使用 FROM 指令指明所基于的镜像名称;
●之后使用 MAINTAINER 指令说明维护该镜像的用户信息;
●然后是镜像操作相关指令,如 RUN 指令。每运行一条指令,都会给基础镜像添加新的一层。
●最后使用 CMD 指令指定启动容器时要运行的命令操作。
七 Dockerfile 安装并打开 apache 案例
1, 代码展示
<code>#建立工作目录
mkdir /opt/apache
cd /opt/apache
vim Dockerfile
#基于的基础镜像
FROM centos:7
#维护镜像的用户信息
MAINTAINER this is apache image <hmj>
#镜像操作指令安装apache软件
RUN yum -y update
RUN yum -y install httpd
#开启 80 端口
EXPOSE 80
#复制网站首页文件
ADD index.html /var/www/html/index.html
//方法一:
#将执行脚本复制到镜像中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
#启动容器时执行脚本
CMD ["/run.sh"]
//方法二:
ENTRYPOINT [ "/usr/sbin/apachectl" ]
CMD ["-D", "FOREGROUND"]
//准备执行脚本
vim run.sh
#!/bin/bash
rm -rf /run/httpd/*#清理httpd的缓存
/usr/sbin/apachectl -D FOREGROUND#指定为前台运行
#因为Docker容器仅在它的1号进程(PID为1)运行时,会保持运行。如果1号进程退出了,Docker容器也就退出了。
//准备网站页面
echo "this is test web" > index.html
//生成镜像
docker build -t httpd:centos . #注意别忘了末尾有"."
//新镜像运行容器
docker run -d -p 1216:80 httpd:centos
//测试
http://192.168.80.10:1216/
########如果有网络报错提示########
[Warning] IPv4 forwarding is disabled. Networking will not work.
解决方法:
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
sysctl -p
systemctl restart network
systemctl restart docker
2, 演示
建立工作目录
vim Dockerfile
index.html 在宿主机上 同步容器里的 /var/www/html/index.html
为什么不需要绝对路径 因为在创建镜像那一步 会指定当前目录
做页面
生成镜像 注意别忘了末尾有"."
. 是当前目录的意思
启动镜像 查看端口号
访问页面 成功
3, 也可以使用脚本的方式
具体见第1 条
八 构建SSH镜像
1,代码展示
<code>cd /opt/sshd
vim Dockerfile
#第一行必须指明基于的基础镜像
FROM centos:7
#作者信息
MAINTAINER this is ssh image <hmj>
#镜像的操作指令
RUN yum -y update
RUN yum -y install openssh* net-tools lsof telnet passwd
RUN echo 'abc1234' | passwd --stdin root
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config#不使用PAM认证
RUN sed -ri '/^session\s+required\s+pam_loginuid.so/ s/^/#/' /etc/pam.d/sshd#取消pam限制
RUN ssh-keygen -t rsa -A#生成密钥认证文件
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
EXPOSE 22
CMD ["/usr/sbin/sshd" , "-D"]#/usr/sbin/sshd -D 用于前台启动sshd服务
//生成镜像
docker build -t sshd:centos .
//启动容器并修改root密码
docker run -d -P sshd:centos
docker ps -a
ssh localhost -p 49155
2, 搭建ssh 镜像演示
创建ssh 目录
写dockerfile vim Dockerfile
<code>RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh:
作用:确保
/root/.ssh
目录存在,并将其权限设置为只有root用户可读写执行,这是SSH密钥存放的标准安全配置。
生成镜像 docker build -t sshd:centos .
启动容器 docker run -d -P sshd:centos
别的机器 ssh 连接该容器
本机 ssh 连接该容器
九 构建 Systemctl镜像
1,代码展示
<code>mkdir /opt/systemctl
cd /opt/systemctl
vim Dockerfile
FROM sshd:centos
MAINTAINER this is systemctl image <hmj>
ENV container docker
#除了systemd-tmpfiles-setup.service,删除其它所有文件
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*; \
rm -f /etc/systemd/system/*.wants/*; \
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
#CMD ["/usr/sbin/init"]
//生成镜像
docker build -t systemd:centos .
//启动容器,并挂载宿主机目录挂载到容器中,和进行初始化
docker run --privileged -d -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init
#--privileged:使container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。
docker ps -a
//进入容器
docker exec -it a0d624d2bfa9 bash
systemctl status sshd
方法二:
docker run --privileged -it -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init &
2, 搭建systemctl 镜像演示
创建systemctl dockerfile 所在目录
vim Dockerfile
生成镜像
启动容器,并挂载宿主机目录挂载到容器中,和进行初始化
进入容器
使用 systemctl
3, dockerfile 讲解
<code>FROM sshd:centos:
作用:指定基础镜像。这里使用的是一个包含了SSH服务的CentOS镜像,具体名称为sshd:centos
。
MAINTAINER this is systemctl image <hmj>
:
注释:声明镜像维护者信息,尽管此指令已被Dockerfile最佳实践所废弃,但这里说明该镜像与systemctl配置相关,维护者为hmj。
ENV container docker
:
作用:设置环境变量container
的值为docker
。这可以被应用程序或脚本用来检测是否在Docker环境中运行。
接下来的几行为删除不必要的Systemd单元文件,以精简系统启动过程并避免在Docker容器中不必要的服务启动。
4-11. RUN (cd ...)
到 rm -f /lib/systemd/system/anaconda.target.wants/*;
:
作用:这一长行RUN指令包含了一系列的删除操作,目的是清理Systemd的默认启动项,仅保留systemd-tmpfiles-setup.service
,因为其他服务对于一个主要运行SSH服务的Docker容器来说是多余的。通过这些操作,确保容器启动更快且资源占用更少,同时也避免了不必要的服务干扰。
VOLUME [ "/sys/fs/cgroup" ]
:
作用:创建一个数据卷挂载点/sys/fs/cgroup
。这通常是为了允许Docker容器内的Systemd正确管理其自身的cgroups(控制组),尤其是在尝试在容器内使用Systemd作为初始化系统时非常重要。
#CMD ["/usr/sbin/init"]
:
注释:这是一个被注释掉的指令,原本打算用来启动Systemd作为容器的入口点。由于被注释,实际构建的镜像不会执行这一行。如果需要在容器中使用Systemd管理服务,可以取消这一行的注释。
总结来说,这个Dockerfile定制了一个以SSH服务为基础,针对Docker容器优化的Systemd环境。它移除了大量默认的Systemd服务启动链接,减少了容器启动负担,并准备了cgroup的挂载点以便更好地兼容Systemd。最后,虽然没有明确启动命令,但通过取消注释CMD指令或添加适当的ENTRYPOINT/CMD,可以控制容器启动时的行为,比如使用Systemd作为初始化系统。
十 nginx镜像
1, 代码演示
mkdir /opt/nginx
cd /opt/nginx/
cp /opt/nginx-1.12.0.tar.gz /opt/nginx
vts
vim Dockerfile
#基于基础镜像
FROM centos:7
#用户信息
MAINTAINER this is nginx image <hmj>
#添加环境包
RUN yum -y update
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make
RUN useradd -M -s /sbin/nologin nginx
#上传nginx软件压缩包,并解压
ADD nginx-1.12.0.tar.gz /opt/
#指定工作目录
WORKDIR /opt/nginx-1.12.0
RUN ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module && make && make install
ENV PATH /usr/local/nginx/sbin:$PATH
#指定http和https端口
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf#关闭 nginx 在后台运行
#添加宿主机中run.sh到容器中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
#CMD ["/usr/local/sbin/nginx", "-g", "daemon off;"]
vim run.sh
#!/bin/bash
/usr/local/nginx/sbin/nginx
//创建新镜像
docker build -t nginx:centos .
docker run -d -P nginx:centos
docker ps -a
5df9e4383b96 nginx:centos "/run.sh" 15 seconds ago Up 15 seconds 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp silly_davinci
http://192.168.80.10:32769
2, 演示 搭建 nginx 镜像
创建dockerfile的目录
安装 wgwt 命令
下载 nginx 的安装包
vim Dockerfile
vi run.sh 写运行脚本
启动容器
访问页面
3, dockerfile 详细解释
这是一个 Dockerfile 的内容,用于构建一个基于 CentOS 7 并包含 Nginx 服务器的 Docker 镜像。下面是对每一行指令的详细解释:
FROM centos:7
作用: 指定基础镜像,这里使用的是 CentOS 7 版本。
MAINTAINER this is nginx image <wyq>
作用: 设置镜像的维护者信息,虽然 Docker 官方推荐使用 <code>LABEL 指令替代此指令,但这里仍然是老式的维护者声明方式,wyq
是维护者的名字或标识。
RUN yum -y update
作用: 更新系统的所有包到最新版,-y
参数表示自动确认所有安装或更新操作,无需人工干预。
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make
作用: 安装编译 Nginx 所需的依赖包,包括PCRE库、Zlib库的开发文件、GCC编译器、C++支持以及Make工具。
RUN useradd -M -s /sbin/nologin nginx
作用: 创建一个名为 nginx
的系统用户,-M
表示不创建用户的家目录,-s /sbin/nologin
表示该用户不能登录系统。
ADD nginx-1.12.0.tar.gz /opt/
作用: 将本地的 nginx-1.12.0.tar.gz
文件复制到容器的 /opt/
目录下。
WORKDIR /opt/nginx-1.12.0
作用: 设置工作目录为 /opt/nginx-1.12.0
,即解压后的 Nginx 源代码目录。
RUN ./configure ... && make && make install
作用: 配置、编译并安装 Nginx。配置参数包括指定安装路径为 /usr/local/nginx
,设置运行用户和组为 nginx
,并启用 HTTP Stub Status 模块以监控状态。
ENV PATH /usr/local/nginx/sbin:$PATH
作用: 设置环境变量 PATH
,将 Nginx 的可执行文件目录 /usr/local/nginx/sbin
添加到系统路径中,这样可以在不指定完整路径的情况下直接运行 nginx
命令。
EXPOSE 80
作用: 声明容器将在端口 80 上监听,用于 HTTP 服务。
EXPOSE 443
作用: 声明容器将在端口 443 上监听,用于 HTTPS 服务。
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf
作用: 修改 Nginx 配置文件,在最后追加一行 daemon off;
,使得 Nginx 在前台运行,这对于 Docker 容器来说是必要的,因为后台运行的服务会导致容器立即退出。
ADD run.sh /run.sh
作用: 将本地的 run.sh
脚本文件复制到容器的 /run.sh
路径下。
RUN chmod 755 /run.sh
作用: 修改 /run.sh
脚本的权限,使其具有执行权限(rwxr-xr-x)。
CMD ["/run.sh"]
作用: 指定容器启动时运行的命令,这里是执行 /run.sh
脚本。
整体来看,这个Dockerfile的目标是创建一个包含Nginx服务的Docker镜像,并配置了一些基本的运行参数,适合于快速部署和管理Nginx服务。不过,需要注意的是,实际构建时应确保 nginx-1.12.0.tar.gz
和 run.sh
文件存在于构建上下文目录中,且版本号 1.12.0
应根据实际情况校验其正确性,因为截至当前知识更新,Nginx并没有明确发布过1.12.0版本。
十一 搭建 tomcat 镜像
1, 代码展示
mkdir /opt/tomcat
cd /opt/tomcat
cp /opt/jdk-8u91-linux-x64.tar.gz /opt/tomcat
cp /opt/apache-tomcat-8.5.16.tar.gz /opt/tomcat
vim Dockerfile
FROM centos:7
MAINTAINER this is tomcat image <hmj>
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 JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-8.5.16.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv apache-tomcat-8.5.16 /usr/local/tomcat
EXPOSE 8080
#CMD ["/usr/local/tomcat/bin/catalina.sh","run"]
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
CMD ["/usr/local/tomcat/bin/startup.sh","start"]
//创建新镜像
docker build -t tomcat:centos .
docker run -d --name tomcat01 -p 1216:8080 tomcat:centos
http://192.168.80.10:1216
2, 演示
创建目录
准备 安装包
vim Dockerfile
创建新镜像
启动容器
访问页面
3, dockerfile 详解
这个 Dockerfile 用于构建一个基于 CentOS 7 的 Tomcat 镜像,下面是每行指令的详细说明:
FROM centos:7
作用:指定基础镜像为 CentOS 7,后续的构建步骤将在这个镜像基础上进行。
MAINTAINER this is tomcat image <hmj>
作用:声明镜像的维护者信息,尽管 Docker 推荐使用 <code>LABEL 指令代替,这里使用了较旧的 MAINTAINER
,hmj
是维护者的名字或邮箱。
ADD jdk-8u291-linux-x64.tar.gz /usr/local/
作用:将本地的 JDK 8u291 版本的 Linux x64 安装包添加到容器内的 /usr/local/
目录。
WORKDIR /usr/local/
作用:设置工作目录为 /usr/local/
,后续的命令将在该目录下执行。
RUN mv jdk1.8.0_291 /usr/local/java
作用:将解压后的 JDK 目录重命名为 java
并移动到 /usr/local/
下,以便统一管理。
ENV JAVA_HOME /usr/local/java
作用:设置环境变量 JAVA_HOME
指向 JDK 的安装目录。
ENV JRE_HOME ${JAVA_HOME}/jre
作用:设置环境变量 JRE_HOME
指向 JDK 中的 JRE 目录。
ENV CLASSPATH .:{JAVA_HOME}/lib:JAVAHOME/lib:{JRE_HOME}/lib
作用:设置类路径(CLASSPATH),包含了当前目录及 Java 库目录,方便 Java 程序找到所需的类和库文件。
ENV PATH JAVA_HOME/bin:JAVAHOME/bin:PATH
作用:将 JDK 的 bin 目录添加到系统路径中,使 java
, javac
等命令可以直接在终端使用。
ADD apache-tomcat-8.5.16.tar.gz /usr/local/
作用:将 Tomcat 8.5.16 的压缩包添加到 /usr/local/
目录。
WORKDIR /usr/local/
再次设置工作目录为 /usr/local/
,为接下来的命令做准备。
RUN mv apache-tomcat-8.5.16 /usr/local/tomcat
作用:将解压后的 Tomcat 目录重命名为 tomcat
并移动到 /usr/local/
下,便于管理。
EXPOSE 8080
作用:声明容器将会监听 8080 端口,这是 Tomcat 默认的 HTTP 端口。
#CMD ["/usr/local/tomcat/bin/catalina.sh","run"]
注释:这行被注释掉了,原本是用来直接运行 Tomcat 的 catalina.sh run
命令,但实际未被采用。
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
作用:设置容器启动时执行的命令,这里是直接运行 Tomcat 的 catalina.sh run
,使 Tomcat 作为主进程启动。
CMD ["/usr/local/tomcat/bin/startup.sh","start"]
作用:虽然有了 ENTRYPOINT
,但这里也设置了 CMD
。理论上,当 ENTRYPOINT
存在时,CMD
会被当作默认参数传递给 ENTRYPOINT
。不过,这里的设置可能导致一些混淆,因为通常直接用 catalina.sh run
就能启动 Tomcat,不需要再调用 startup.sh start
。正确的实践应该是选择 ENTRYPOINT
或 CMD
其中之一来启动 Tomcat。
综上所述,这个 Dockerfile 主要目的是创建一个包含特定版本 JDK 和 Tomcat 8.5.16 的容器镜像,配置好必要的环境变量和启动命令,以便于运行 Java Web 应用。但最后的 ENTRYPOINT
和 CMD
可能需要根据实际需求调整,避免冲突或冗余。
十二 dockerfile 搭建 mysqld
1, 代码展示
mkdir /opt/mysqld
cd /opt/mysqld
vim Dockerfile
FROM centos:7
MAINTAINER this is mysql image <hmj>
RUN yum -y install ncurses ncurses-devel bison cmake pcre-devel zlib-devel gcc gcc-c++ make;useradd -M -s /sbin/nologin mysql
ADD mysql-boost-5.7.20.tar.gz /usr/local/src/
WORKDIR /usr/local/src/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 -j4;make install
ADD my.cnf /etc/my.cnf
EXPOSE 3306
RUN chown -R mysql:mysql /usr/local/mysql/;chown mysql:mysql /etc/my.cnf
WORKDIR /usr/local/mysql/bin/
RUN ./mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data;cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/;systemctl enable mysqld
ENV PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
VOLUME [ "/usr/local/mysql" ]
CMD ["/usr/sbin/init"]
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
vim run.sh
#!/bin/bash
/usr/local/mysql/bin/mysqld
systemctl enable mysqld
//创建新镜像
docker build -t mysql:centos .
//启动容器,并进行初始化
docker run --name=mysql_server -d -P --privileged mysql:centos /usr/sbin/init
//进容器给权限
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f9a4d8f6c65f mysql:centos "/usr/sbin/init" 17 seconds ago Up 16 seconds 0.0.0.0:49153->3306/tcp mysql_server
//进入容器,授权远程连接 mysql
docker exec -it f9a4d8f6c65f /bin/bash
mysql -u root -p
grant all privileges on *.* to 'root'@'%' identified by 'abc123';
grant all privileges on *.* to 'root'@'localhost' identified by 'abc123';
flush privileges;
//在客户端连接mysql容器
mysql -h 192.168.80.10 -u root -P 49153 -pabc123
2, 演示
准备创建目录 和安装包
vim Dockerfile
vim my.cnf
vim run.sh
创建新镜像
3, dockerfile 代码详解
这个 Dockerfile 用于构建一个基于 CentOS 7 的 MySQL 5.7.20 镜像。下面是每一行命令的详细解释:
FROM centos:7
基于 CentOS 7 的官方镜像开始构建。
MAINTAINER this is mysql image <hmj>
指定镜像的维护者信息,虽然现在推荐使用 <code>LABEL 指令。
RUN yum -y install ...; useradd -M -s /sbin/nologin mysql
安装一系列依赖包,包括ncurses、gcc等开发工具,以及为MySQL用户创建系统账户,不允许登录(-M)且指定shell为nologin。
ADD mysql-boost-5.7.20.tar.gz /usr/local/src/
将MySQL源码包添加到容器的/usr/local/src/
目录中。
WORKDIR /usr/local/src/mysql-5.7.20/
切换工作目录到MySQL源码解压后的目录。
RUN cmake ...; make -j4; make install
使用cmake配置MySQL编译选项,如安装路径、字符集、存储引擎等,然后并行编译(-j4
)并安装MySQL。
ADD my.cnf /etc/my.cnf
添加自定义的MySQL配置文件到容器的/etc目录。
EXPOSE 3306
声明容器将在3306端口监听,这是MySQL默认端口。
RUN chown ...; chown ...
更改MySQL数据目录和配置文件的属主和属组为mysql用户。
WORKDIR /usr/local/mysql/bin/
切换工作目录到MySQL的bin目录。
RUN ./mysqld ...
初始化MySQL数据库,不设置root密码(--initialize-insecure
),指定用户、基目录和数据目录,初始化数据库结构。
RUN cp ...; systemctl enable mysqld
复制MySQL服务单元文件到系统目录,并设置开机启动MySQL服务。
ENV PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
设置环境变量PATH,使得MySQL的可执行文件路径可以全局访问。
VOLUME [ "/usr/local/mysql" ]
定义数据卷挂载点,允许容器外访问MySQL的数据目录。
CMD ["/usr/sbin/init"]
指定容器启动时运行的命令,这里使用系统初始化脚本,意在使用Systemd管理服务,包括MySQL服务。但注意,在某些Docker环境或场景中,直接使用Systemd可能不适用,可能需要调整为直接启动MySQL服务的命令。
这个Dockerfile展示了从源码编译安装MySQL并进行基本配置的过程,适用于需要高度定制MySQL环境的场景。不过,直接从源码编译可能比直接使用预编译的二进制包更复杂且耗时。
十三 镜像容量过大的解决方案
基础镜像尽量使用轻量级最小化的镜像。Dockerfile 中尽量把 RUN 指令合并在一起,减少镜像的层数(因为每一个RUN指令就是一个镜像层)。多级构建(拿 Dockerfile 构建好的镜像再构建一次)
十四 总结
1、dockerfile 构建镜像的步骤
先用FROM 指令指定基础镜像
再用MAINTINER 指定维护人信息
然后再用 RUN EXPOSE ADD ENV USER WORKDIR指令编写镜像的过程
最后使用 CMD 或者 ENTPYONT 指令指定启动容器时执行的命令
2、ENTPYONT CMD 区别
容器启动时执行命令的优先级
docker run --entypont=命令 镜像 选项 参数 ---> ENTPYONT ["命令","选顶","参数”] ---> docker run 镜像 命令 选项 参数 ---> CMD ["命令","选项","参数"]
如果在同一个 dockerfile 文件中同时存在 ENTPYONT 和 CMD 时,ENTPYONT 会覆盖 CMD 运行命令,CMD 为提供选项和参数
3、ADD 和 COPY 区别
都可以复制本地文件/目录到镜像中
ADD 可以通过URL路径下 文件并复制到镜像 还可以把本地的tar压缩包进行解压后复制到镜像COPY 支持配合 --from= 选项 实现多个阶段构建
4、如何缩小 dockerfile 构建的镜像体积大小?
仅可能减少指令的数量,比如把 RUN 的 linux 命令进行合并
仅可能的使用最简洁的基础镜像
使用多阶段(多级)构建
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。