一、前言
记录时间 [2024-4-12]
系列文章简摘:
Docker学习笔记(二):在Linux中部署Docker(Centos7下安装docker、环境配置,以及镜像简单使用)
Docker 学习笔记(三):Centos7 中 Docker 使用,镜像、容器,以及操作等常用命令小结
Docker 学习笔记(五):梳理 Docker 镜像知识,附带 Commit 方式提交镜像副本,安装可视化面板 portainer
Docker 学习笔记(六):挑战容器数据卷技术一文通,实战多个 MySQL 数据同步,能懂会用,初学必备
更多 Docker 相关文章请参考上面专栏哦,入门篇 1~5 已完结,6 开始是精髓篇:容器数据卷、Dockerfile、Docker 网络。
本文主要介绍 Dockerfile,包括 Dockerfile 的构建过程、Dockerfile 的指令,以及 Dockerfile 的使用方式。通过实战,学会使用 Dockerfile 构建自己的 centos 镜像,讲述了 CMD 和 ENTRYPOINT 的区别,解决基础镜像 centos 无法使用 yum -y
命令的问题。
学习工具包:
- Docker 学习视频
- Docker 官方文档
- Docker 远程仓库
- Linux 云服务器/虚拟机
- FinalShell 远程连接工具
二、Dockerfile 介绍
Dockerfile 是用来构建 Dokcer 镜像的文件,是一种命令参数脚本。
构建步骤如下:
- 编写一个 Dockerfile
- docker build 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub / 阿里云镜像仓库)
在 DockerHub 中搜索 centos
:
我们来查看下 centos7 的 Dockerfile 脚本:
# scratch 是一个基础镜像,90% 的镜像来源于它
# 基于 scratch,然后添加需要的软件和配置来进行构建
FROM scratch
# 添加一个压缩包
ADD centos-7-x86_64-docker.tar.xz /
# 添加标签
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
# 控制台方式运行
CMD ["/bin/bash"]
不难发现,大部分官方镜像都是基础包,功能很少,在使用中我们通常会搭建自己的镜像。
接下来我们尝试自己制作镜像。
三、Dockerfile 构建过程
基础知识:
- 保留关键字(指令)必须是大写字母
- 指令从上到下顺序执行
#
表示注释- 每一个指令都会创建并提交一个新的镜像层
Dockerfile 面向开发,通过编写 Dockerfile 文件,我们可以构建镜像、发布项目。
- Dockerfile:构建文件,相当于源代码,定义了所有步骤;
- DockerImage:通过 Dockerfile 构建生成的镜像;
- DockerContainer:容器提供镜像运行的服务器。
Docker 镜像逐渐成为企业交付的标准,实现开发,部署,运维全流程。
四、Dockerfile 指令
了解这些指令后,我们就可以构建自己的 Docker 镜像。
Dockerfile 中常用的指令有:
FROM
:基础镜像,一切从这里开始构建。MAINTAINER
:镜像是谁写的?姓名 + 邮箱。RUN
:镜像构建的时候需要运行的命令。ADD
:添加构建内容,如构建 tomcat 镜像,就添加 tomcat压缩包。WORKDIR
:镜像的工作目录。VOLUME
:挂载的目录。EXPOSE
:暴露端口配置。CMD
:指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代。ENTRYPOINT
:指定这个容器启动时要运行的命令,可以追加命令。ONBUILD
:当构建一个被继承的 Dockerfile 时,会运行 ONBUILD 指令,触发指令。COPY
:类似 ADD,将文件拷贝到镜像中。ENV
:构建的时候设置环境变量。
五、实战测试
实战测试:使用 Dockerfile 创建自己的 centos 镜像。
1. 准备工作
先看一眼官方创建的 centos
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
运行下官方镜像,发现缺失了很多命令:
[root@localhost ~]# docker run -it centos
# 运行在根目录 /
[root@352a2c999b35 /]# pwd
/
# 没有 vim 命令
[root@352a2c999b35 /]# vim
bash: vim: command not found
# 没有 ifconfig 命令
[root@352a2c999b35 /]# ifconfig
bash: ifconfig: command not found
2. 编写 Dockerflie 文件
创建一个目录用来存放项目文件
[root@localhost ~]# mkdir /home/dockerfile
[root@localhost ~]# cd /home/dockerfile
在该目录下,新建 mydockerfile-centos 文件
vim mydockerfile-centos
编写文件:i
写入文件并 :wq
保存
FROM centos
MAINTAINER yuanyuan<1234567@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----------end--------"
CMD /bin/bash
写完后查看一下:
cat mydockerfile-centos
3. 通过文件构建镜像
# docker build -f dockerfile文件路径 -t 镜像名:版本号 .
docker build -f mydockerfile-centos -t mycentos:0.1 .
4. 报错解决
没报错就跳到下一步
错误描述
发现构建遇到报错:
ERROR [3/4] RUN yum -y install vim
Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist
错误原因:
- 网络连接的问题,使用
ping baidu.com
检查是否可以连接外部网络; - centos 停止维护的问题,具体看公告,笔者遇到的是这种。
解决方式:替换基础镜像。
因为我们上面用的 FROM centos,官方基础镜像 centos 停止维护,所以我们要从 centos 镜像入手。
自己 commit 一个 centos 镜像。
问题分析
先运行下官方基础镜像 centos:
docker run -it centos
去查看 yum 的配置文件:
[root@62111d10f8a3 /]# cd /etc/yum.repos.d/
[root@62111d10f8a3 yum.repos.d]# ls
CentOS-Linux-AppStream.repo CentOS-Linux-Devel.repo CentOS-Linux-Media.repo
CentOS-Linux-BaseOS.repo CentOS-Linux-Extras.repo CentOS-Linux-Plus.repo
CentOS-Linux-ContinuousRelease.repo CentOS-Linux-FastTrack.repo CentOS-Linux-PowerTools.repo
CentOS-Linux-Debuginfo.repo CentOS-Linux-HighAvailability.repo CentOS-Linux-Sources.repo
随便挑一个配置文件看看:
[root@62111d10f8a3 yum.repos.d]# cat CentOS-Linux-AppStream.repo
# CentOS-Linux-AppStream.repo
#
# The mirrorlist system uses the connecting IP address of the client and the
# update status of each mirror to pick current mirrors that are geographically
# close to the client. You should use this for CentOS updates unless you are
# manually picking other mirrors.
#
# If the mirrorlist does not work for you, you can try the commented out
# baseurl line instead.
[appstream]
name=CentOS Linux $releasever - AppStream
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/AppStream/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
发现重点:如果 mirrorlist 不能用,就换成 baseurl 试试。
# If the mirrorlist does not work for you, you can try the commented out
# baseurl line instead.
思路就是把 mirrorlist 替换成 baseurl
但是测试发现 baseurl 通过 mirror.centos.org 也无法下载 appstream,所以替换成 vault.centos.org
总之就是要把镜像替换成能用的。
解决步骤
接下来开始替换:
- 把
mirrorlist
替换成#mirrorlist
- 把
#baseurl=http://mirror.centos.org
替换成baseurl=http://vault.centos.org
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
生成更新缓存
yum makecache
更新 yum
yum update -y
这样就把 yum 不能安装的问题解决了,exit 退出容器吧(记住这个容器的 id )
我们把这个容器 commit 提交为本地镜像,yuanyuan/centos
是笔者给新镜像的仓库命名。
不加版本号,默认是最新版。
docker commit -a="yuanyuan" -m="yum update -y to centos" 容器id yuanyuan/centos
然后把 Dockerfile 中的基础镜像修改为这个:
vim mydockerfile-centos
# 修改第一行为
FROM yuanyuan/centos
重新构建
重新 build 一下吧
docker build -f mydockerfile-centos -t mycentos:0.1 .
成功!
5. 测试运行 mycentos
测试运行 mycentos 发现,进入容器时,直接进入了工作目录。
且 vim
,ifconfig
命令能用了。
[root@localhost dockerfile]# docker run -it mycentos:0.1
# 直接进入了工作目录 WORKDIR
[root@ab9ef08ece02 local]# pwd
/usr/local
# vim ifconfig 命令能用了
[root@ab9ef08ece02 local]# vim test
[root@ab9ef08ece02 local]# ifconfig
eth0: flags=...
lo: flags=...
6. 进行对比
镜像类型 | 运行进入目录 | 命令情况 |
---|---|---|
官方版本 centos | 根目录 | 命令缺失 |
构建版本 mycentos | 工作目录 | vim ,ifconfig 命令能用了 |
7. 查看镜像变更历史
列出本地镜像变更历史,查看 mycentos 镜像的构建过程
docker history 镜像id
通过这种方式,我们可以研究镜像的制作过程。
六、CMD 和 ENTRYPOINT 的区别
1. CMD 用法
Dockerfile 构建镜像
新建 CMD 测试文件
vim dockerfile-cmd-test
编写 Dockerfile
FROM centos
CMD ["ls", "-a"]
# ls -a 展现当前基本目录,镜像运行的时候会执行这个命令
构建镜像
docker build -f dockerfile-cmd-test -t cmdtest .
运行镜像
ls -a
展现当前基本目录,镜像运行的时候会执行这个命令
run
运行发现,ls -a
命令生效
[root@localhost dockerfile]# docker run cmdtest
.
..
.dockerenv
bin
dev
etc
home
追加参数试试,想追加一个命令 -l
,组成 ls -al
发现报错了,CMD 情况下,-l
替换了 CMD ["ls", "-a"]
,而 -l
不是命令,所以报错。
[root@localhost dockerfile]# docker run cmdtest -l
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
正确的使用方法是:
docker run cmdtest ls -al
2. ENTRYPOINT 用法
Dockerfile 构建镜像
新建 ENTRYPOINT 测试文件
vim dockerfile-entrypoint-test
编写 Dockerfile
FROM centos
ENTRYPOINT ["ls", "-a"]
构建镜像
docker build -f dockerfile-entrypoint-test -t entrypoint-test .
运行镜像
ls -a
展现当前基本目录,镜像运行的时候会执行这个命令
run
运行发现,ls -a
命令生效
[root@localhost dockerfile]# docker run entrypoint-test
.
..
.dockerenv
bin
dev
etc
home
追加参数试试,发现命令依然生效!
我们追加的参数,是直接拼接在 ENTRYPOINT 命令的后面
[root@localhost dockerfile]# docker run entrypoint-test -l
total 56
drwxr-xr-x 1 root root 4096 Apr 12 09:48 .
drwxr-xr-x 1 root root 4096 Apr 12 09:48 ..
-rwxr-xr-x 1 root root 0 Apr 12 09:48 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
3. 二者区别
CMD
:指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代。ENTRYPOINT
:指定这个容器启动时要运行的命令,可以追加命令。
在 Dockerfile 中,类似 CMD 和 ENTRYPOINT 这样的相似命令还有很多。可以通过对比学习,来测试它们的使用效果。
七、总结
本文主要介绍 Dockerfile,包括 Dockerfile 的构建过程、Dockerfile 的指令,以及 Dockerfile 的使用方式。还通过实战,学会使用 Dockerfile 构建自己的 centos 镜像,讲述了 CMD 和 ENTRYPOINT 的区别,解决基础镜像 centos 无法使用 yum -y
命令的问题。
接下来将尝试使用 Dockerfile 制作 Tomcat 镜像,介绍如何将本地镜像发布到 DockerHub 和阿里云镜像仓库。
一些参考资料
狂神说系列 Docker 教程:https://www.bilibili.com/video/BV1og4y1q7M4/
Docker 官方文档:https://docs.docker.com/engine/install/centos/
Docker 远程仓库:https://hub.docker.com/
FinalShell 下载:http://www.hostbuf.com/t/988.html
CentOS 公告:https://blog.centos.org/2020/12/future-is-centos-stream/