docker入门(八)—— dockerfile详细介绍,编写dockerfile
CSDN 2024-07-15 08:07:02 阅读 86
dockerfile(重点)
大家想想,Nginx,tomcat,mysql 这些镜像都是哪里来的?官方能写,我们不能写吗?
我们要研究自己如何做一个镜像,而且我们写的微服务项目打包上云部署,docker 就是最方便的。
微服务打包成镜像,任何装了 docker 的地方,都可以下载使用,极其方便。
流程:开发应用 => 编写 dockerfile => 打包为镜像 => 上传到仓库(私有仓库公司内部,公有仓库 dockerhub)=> 下载镜像 => 启动运行。
还可以方便移植!
什么是 dockerfile
dockerfile 是一种用于定义和构建 docker 镜像的文本文件。它包含一系列的指令和参数,用于描述镜像的构建过程,包括基础映像、软件包安装、文件拷贝、环境变量设置等。
通过编写 dockerfile,可以将应用程序、环境和依赖项打包成一个独立的容器镜像,使其可以在不同的环境和平台上运行,实现应用程序的可移植性和可扩展性。
dockerfile 的基本结构包括以下几个部分:
基础映像(Base Image):使用 FROM 指令指定基础映像,作为构建镜像的起点。基础映像通常包含了操作系统和一些预装的软件和工具。构建过程指令:使用一系列指令来描述构建过程,例如 RUN 用于执行命令和安装软件包,COPY 用于拷贝文件和目录,ADD 用于拷贝和提取文件,WORKDIR 用于设置工作目录,等等。容器启动指令:使用 CMD 或 ENTRYPOINT 指令来定义容器启动时要执行的命令,也就是默认的容器执行命令。
通过编写 dockerfile,可以自定义构建过程,选择所需的软件和配置,以及设置环境变量、暴露端口等。dockerfile 的语法简单且易于理解,使得镜像的构建过程变得可重复和可维护。
总的来说,dockerfile 是定义和构建 docker 镜像的文本文件,通过编写指令和参数来描述镜像的构建过程和配置,以实现应用程序的打包和部署。它是使用 docker 进行容器化开发和部署的重要工具。
构建步骤:
编写 dockerfile 文件docker build 构建镜像docker run 镜像
dockerfile 构建过程
基础知识:
每条保留字指令都必须为大写字母且后面要跟随至少一个参数指令按照从上到下,顺序执行<code># 表示注释每条指令都会创建一个新的镜像层,并对镜像进行提交
流程:
docker 从基础镜像运行一个容器执行一条指令并对容器做出修改执行类似 docker commit 的操作提交一个新的镜像层docker 再基于刚提交的镜像运行一个新容器执行 dockerfile 中的下一条指令直到所有指令都执行完成!
说明:
从应用软件的角度来看,dockerfile,docker 镜像与 docker 容器分别代表软件的三个不同阶段。
dockerfile 是软件的原材料(代码)docker 镜像则是软件的交付品(.apk)docker 容器则是软件的运行状态(客户下载安装执行)
dockerfile 面向开发,docker 镜像成为交付标准,docker 容器则涉及部署与运维,三者缺一不可!
dockerfile:需要定义一个 dockerfile,dockerfile 定义了进程需要的一切东西。dockerfile 涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace 的权限控制)等等。docker镜像:在 dockerfile 定义了一个文件之后,docker build 时会产生一个 docker 镜像,当运行 docker 镜像时,会真正开始提供服务;docker容器:容器是直接提供服务的。
dockerfile 指令
关键字:
<code>FROM # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER # 镜像维护者的姓名混合邮箱地址
RUN # 容器构建时需要运行的命令
EXPOSE # 当前容器对外保留出的端口
WORKDIR # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
ENV # 用来在构建镜像过程中设置环境变量
ADD # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY # 类似ADD,拷贝文件和目录到镜像中!
VOLUME # 容器数据卷,用于数据保存和持久化工作
CMD # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最后一个生效!
ENTRYPOINT # 指定一个容器启动时要运行的命令!和CMD一样
ONBUILD # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发
编写 dockerfile
dockerhub 中99%的镜像都是通过在 base 镜像(Scratch)中安装和配置需要的软件构建出来的
Scratch 镜像很赞,它简洁、小巧而且快速,它没有 bug、安全漏洞、延缓的代码或技术债务。除了被 docker 添加了 metadata 之外,它基本上是空的。
我们在使用 dockerfile 构建 docker 镜像时,一种方式是使用官方预先配置好的容器镜像。优点是我们不用从头开始构建,节省了很多工作量,但付出的代价是需要下载很大的镜像包。
如果我们的需求是在构建一个符合我们实际业务需求的 docker 镜像的前提下,确保镜像尺寸尽可能的小,应该怎么做呢?
思路是使用空镜像 scratch,可以说是真正的从零开始构建属于自己的镜像,镜像的第一层
发布一个自己编写的 centos
由于阿里云官方的 centos 是不完整的,很多命令都没有(例如 vim、ipconfig 等),我们自定义一个 centos 镜像,,让它能够拥有这些命令
<code># dockerfile文件名字可以任意取,最好为Dockerfile
vim Dockerfile
编写 dockerfile 如下:
FROM centos7.9.2009
MAINTAINER akuya<123456@qq.com>
# 配置环境以及工作目录
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 安装vim、ipconfig等命令
RUN yum -y install vim
RUN yum -y install net-tools
# 暴露端口
EXPOSE 80
CMD echo $MYPATH
CMD echo "---akuya---"
CMD /bin/bash
由于最新版 centos8 有 bug,故使用 centos7.9版本
根据 dockerfile 构建镜像
docker build .
参数:
-f
:等价于--file
,指定 dockerfile 文件-t
:等价于--tag
,指定输出的镜像文件名:版本号
命令最后一定要加一个.
# 构建镜像命令
docker build -f Dockerfile -t mycentos:1.0 .
[root@iZbp15293q8kgzhur7n6kvZ home]# docker build -f Dockerfile -t mycentos:1.0 .
[+] Building 54.3s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 282B 0.0s
=> [internal] load metadata for docker.io/library/centos:7.9.2009 15.7s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/4] FROM docker.io/library/centos:7.9.2009@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987 10.0s
=> => resolve docker.io/library/centos:7.9.2009@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987 0.0s
=> => sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987 1.20kB / 1.20kB 0.0s
=> => sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f 529B / 529B 0.0s
=> => sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9 2.75kB / 2.75kB 0.0s
=> => sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc 76.10MB / 76.10MB 6.1s
=> => extracting sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc 3.4s
=> [2/4] WORKDIR /usr/local 2.2s
=> [3/4] RUN yum -y install vim 21.2s
=> [4/4] RUN yum -y install net-tools 3.4s
=> exporting to image 1.7s
=> => exporting layers 1.7s
=> => writing image sha256:1e7fb59b8a162a54a01bc41930d654d7d474cbd7ade3d110f12d95727e1d193f 0.0s
=> => naming to docker.io/library/mycentos:1.0 0.0s
[root@iZbp15293q8kgzhur7n6kvZ home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 1.0 1e7fb59b8a16 About a minute ago 708MB
centos latest 5d0da3dc9764 2 years ago 231MB
根据这个镜像运行容器后发现并没有打印出目录/usr/local
和---akuya---
,这是因为 CMD 指令如果存在多个,只有最后一个会被执行
docker history
查看镜像的变更历史
如果你下载了一个镜像,报错了或者你想查看一些构建逻辑,使用 docker history
[root@iZbp15293q8kgzhur7n6kvZ home]# docker history mycentos:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
1e7fb59b8a16 7 minutes ago CMD ["/bin/sh" "-c" "/bin/bash"] 0B buildkit.dockerfile.v0
<missing> 7 minutes ago CMD ["/bin/sh" "-c" "echo \"---akuya---\""] 0B buildkit.dockerfile.v0
<missing> 7 minutes ago CMD ["/bin/sh" "-c" "echo $MYPATH"] 0B buildkit.dockerfile.v0
<missing> 7 minutes ago EXPOSE map[80/tcp:{ }] 0B buildkit.dockerfile.v0
<missing> 7 minutes ago RUN /bin/sh -c yum -y install net-tools # bu… 208MB buildkit.dockerfile.v0
<missing> 7 minutes ago RUN /bin/sh -c yum -y install vim # buildkit 296MB buildkit.dockerfile.v0
<missing> 7 minutes ago WORKDIR /usr/local 0B buildkit.dockerfile.v0
<missing> 7 minutes ago ENV MYPATH=/usr/local 0B buildkit.dockerfile.v0
<missing> 7 minutes ago MAINTAINER akuya<123456@qq.com> 0B buildkit.dockerfile.v0
<missing> 2 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 2 years ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
项目中编写 dockerfile 思路
基于一个空的镜像下载需要的环境 ADD执行环境变量的配置 ENV执行一些Linux命令 RUN日志 CMD端口暴露 EXPOSE挂载数据卷 VOLUMES
这个过程就是你手动部署项目的过程,你通过 docker 可以再未来实现自动化构建。
CMD 与 ENTRYPOINT 区别
两个命令都是指定一个容器启动时要运行的命令,但二者有很大的区别
CMD
:容器内有多个 CMD 指令时,只有最后一个 CMD 指令会生效,而如果在执行docker run
命令时携带了其它命令,将会覆盖掉所有 dockerfile 的 CMD 指令
ENTRYPOINT
:ENTRYPOINT 的命令不容易被覆盖。在docker run
命令中提供的任何参数都会作为 ENTRYPOINT 命令的参数传递。
当两者组合使用时:那么 CMD 将作为 ENTRYPOINT 的默认参数,如果在docker run
命令中提供了参数,它将覆盖 CMD 并作为 ENTRYPOINT 的参数传递。
例如:
FROM centos
CMD ["echo", "hello world"]
运行容器时,可以覆盖默认的 CMD:
docker build -f Dockerfile -t cmdtest .
docker run cmdtest /bin/bash
结果不会打印出hello world
使用 ENTRYPOINT 指令:
FROM centos
ENTRYPOINT ["echo", "hello "]
CMD ["world"]
运行容器时,可以传递参数给 ENTRYPOINT:
docker build -f Dockerfile -t entrytest .
docker run entrytest # 输出hello world
docker run entrytest akuya# 输出hello akuya
练习:构建一个 tomcat,编写首页
使用空镜像从零构建一个完整的 tomcat
一般一个项目都在一个文件夹中,我们只需要在项目目录下编辑一个 Dockerfile 文件即可
当执行docker bulid
指定时如果没有-f
参数指定 dockerfile 文件,会默认寻找项目目录下的 Dockerfile
来构建镜像,所以我们名字通常设定为Dockerfile
准备工作:准备 tomcat 和 jdk 的 jar 包,创建Dockerfile
文件,以及一个任意内容的readme.md
即可
编辑<code>Dockerfile,内容如下:
FROM centos:7.9.2009
MAINTAINER akuya<123456@qq.com>
# 宿主机目录下文件拷贝到容器内,文件如果不是绝对路径会默认寻找 dockerfile 文件的同级目录下,所以最好所有文件都在同一个目录下
COPY readme.md /usr/local/readme.md
# 添加我们自己的安装包
ADD jdk-8u11-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.22.tar.gz /usr/local
#安装vim编辑器
RUN yum -y install vim
# 配置工作目录
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 配置环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 暴露端口
EXPOSE 8080
# 启动的时候自动运行tomcat,打印日志
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out
构建并运行:
# 构建,不指定 dockerfile 文件会自动寻找该目录下的 Dockerfile
docker build -t mytomcat .
# 运行
docker run -d -p 8080:8080 --name mytomcat \
-v /root/mytomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test \
-v /root/mytomcat/logs:/usr/local/apache-tomcat-9.0.22/logs \
--privileged=true \
mytomcat
运行成功后打开浏览器,输入ip地址:8080
,即可访问到 tomcat 主页
在我们自定义的 tomcat 服务器中上传一个项目,在本地挂载目录,丢一个项目上去。
首先进入到我们挂载的宿主机目录下<code>/root/mytomcat下
[root@iZbp15293q8kgzhur7n6kvZ mytomcat]# cd /root/mytomcat/
[root@iZbp15293q8kgzhur7n6kvZ mytomcat]# ll
total 8
drwxr-xr-x 2 root root 4096 Mar 21 14:45 logs
drwxr-xr-x 2 root root 4096 Mar 21 14:45 test
在 test 目录下丢项目即可
示例:编写一个index.html
<!DOCTYPE html>
<html lang="en">code>
<head>
<meta charset="UTF-8">code>
<title>docker test</title>
</head>
<body>
<h1>----------hello akuya----------------</h1>
<br>
<h2>my docker tomcattest</h2>
</body>
<script>
console.log("my docker tomcat log")
</script>
</html>
浏览器访问ip地址:8080/test/
发布镜像
公有仓库:DockerHub
目前 DockerHub 网址无法访问,了解即可
注册dockerhub https://hub.docker.com/signup,需要有一个账号
发布镜像遵循以下几个步骤:
登录用户:
<code>docker login
参数:
-u
:等价于--username
,登录所需的用户名-p
:等价于--password
,密码
给要上传的镜像打上标签
docker tag 镜像id 镜像名:版本号
上传镜像
docker push 镜像名:版本号
私有仓库,一般都是公司内部自行搭建的,步骤跟上述相同
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。