Dockerfile 若何编写与构建?

刚刚阅读1回复0
kewenda
kewenda
  • 管理员
  • 注册排名1
  • 经验值150395
  • 级别管理员
  • 主题30079
  • 回复0
楼主

Dockerfile 是一个用来构建镜像的文本文件,文本内容包罗了一条条构建镜像所需的指令和申明。 通过Dockerfile我们可以将项目构建成一个镜像,如许的益处是能够将一个复杂的项目间接打包成一个镜像存储和运行。

Dockerfile供给了十分多的指令供我们操做,下面例举一些常用的号令:

指令感化FROM指定当前镜像是基于哪个镜像的RUN构建镜像时需要运行的指令EXPOSE当前容器对外表露的端标语WORKDIR指定在创建容器后末端默认登录进来的工做目次ENV用于在构建镜像过程中设置情况变量ADD将宿主机目次下的文件拷贝到镜像COPY拷贝文件和目次到镜像VOLUME容器数据卷,用于数据耐久化CMD指定一个容器启动时要运行的号令ENTRYPOINT指定一个容器启动时要运行的号令FROM

该指令用于指定当前镜像是基于哪个镜像停止构建的,因为镜像的构建是一层一层停止的,Docker Server会先基于某个根底镜像将项目打包成一个新镜像,再基于那个新镜像继续打包,以此类推,不竭打包构建,最末生成一个处置完成的镜像。

下面就来简单地利用一下FROM指令,在/opt目次下新建一个test目次,并创建Dockerfile文件,编写如下内容:

FROM centos

文件内容十分简单,此时我们就能够按照Dockerfile停止镜像构建了,施行指令:

docker build -t mycentos_test01 .

那里我们指定FROM为centos,Docker Server将基于centos镜像停止构建,当Docker中没有该镜像时,还会先将centos镜像拉取下来再停止构建,

.

暗示Dockerfile文件所在的位置为当前目次:

[root@localhost test]# docker build -t mycentos_test01 . Sending build context to Docker daemon 2.048kB Step 1/1 : FROM centos latest: Pulling from library/centos 7a0437f04f83: Pull complete Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1 Status: Downloaded newer image for centos:latest ---> 300e315adb2f Successfully built 300e315adb2f Successfully tagged mycentos_test01:latest

当指令施行胜利后,就会生成一个新的镜像,能够利用

docker images

指令停止查看:

[root@localhost test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 300e315adb2f 7 months ago 209MB mycentos_test01 latest 300e315adb2f 7 months ago 209MB

此时我们就能够启动那个镜像,同时进入交互末端:

docker run -it mycentos_test01 [root@31c51ab4d120 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

能够看到那就是一个新的centos,那是因为我们只利用了FROM指令基于centos镜像构建,所以得到的镜像仍然仍是一个根底的centos镜像。

需要留意的是Dockerfile文件中的第一条指令必需是

FROM RUN

该指令会将在当前镜像之上的新层中施行任何号令并提交成果,生成的镜像将用于下一步。 修改Dockerfile文件,内容如下:

FROM centos RUN yum install -y vim

我们晓得在没加RUN号令之前构建出来的镜像就是一个centos,但如今,构建出来的镜像就是一个包罗vim编纂器的centos系统,马上来构建它:

docker build -t mycentos_test02 .

构建胜利后就能够停止启动:

docker run -it mycentos_test02

能够查抄一下镜像中能否实的已经包罗了vim编纂器:

[root@46992a057ea4 /]# rpm -qa|grep vim vim-minimal-8.0.1763-15.el8.x86_64 vim-common-8.0.1763-15.el8.x86_64 vim-enhanced-8.0.1763-15.el8.x86_64 vim-filesystem-8.0.1763-15.el8.noarch

RUN指令还撑持以数组的体例传递需要施行的号令,好比:

RUN ["yum","install","-y","vim"] EXPOSE

该指令用于指定构建的镜像在运行时为对外表露的端口,只要向外表露了端口,外部才气够拜候到那个进镜像供给的办事。 修改Dockerfile文件:

FROM centos RUN ["yum","install","-y","vim"] EXPOSE 80

但事实上centos镜像添加端口并没有感化,因为它不像tomcat、mysql、redis那样会向外部主机供给某项办事,所以能够将根底镜像指定为tomcat:

FROM tomcat:8.0

此时构建镜像然后启动:

docker run -p 80:80 mytomcat_test01 CMD

该指令用于为启动的容器指定需要施行的号令,修改Dockerfile:

FROM centos RUN ["yum","install","-y","vim"] EXPOSE 80 CMD ["echo","hello"]

构建镜像:

docker build -t mycentos_test03

此时启动镜像:

docker run -it mycentos_test03

因为CMD指令的感化,所以在启动那个镜像的时候就会立马施行CMD中的号令,从而输出

hello

字符串:

[root@localhost test]# docker run -it mycentos_test03 hello

需要留意的是Dockerfile中只能有一条CMD号令,若是写出了多条CMD,则以最初一条的内容为准。

ENTRYPOINT

该指令与CMD类似,也是用于指定容器启动时需要施行的号令,修改Dockerfile文件:

FROM centos RUN ["yum","install","-y","vim"] EXPOSE 80 ENTRYPOINT ["echo","hello"]

构建镜像:

docker build -t mycentos_test04 .

启动镜像:

[root@localhost test]# docker run -it mycentos_test04 hello

能够看到ENTRYPOINT和CMD两个指令的效果是一样的,那么它俩有什么区别呢?其区别在于号令的笼盖体例,关于CMD指令,我们能够在启动镜像的时候间接拼写号令来笼盖它,好比:

[root@localhost test]# docker run -it mycentos_test03 echo hello centos hello centos

此时在Dockerfile中设置装备摆设的CMD号令将会被那里的

echo hello centos

笼盖掉,最末输出

hello cnetos

然而关于ENTRYPOINT,它是无法通过间接逃加号令来笼盖的,而是需要用到一个参数:

[root@localhost test]# docker run --entrypoint="echo hello centos" mycentos_test04 hello centos

由此可见,ENTRYPOINT指令关于号令的笼盖是比CMD指令愈加复杂的,为此,能够将那些根本固定稳定的号令设置装备摆设到ENTRYPOINT中,而将需要修改的号令设置装备摆设到CMD中,好比:

FROM centos RUN ["yum","install","-y","vim"] EXPOSE 80 ENTRYPOINT ["echo"] CMD ["hello centos"] WORKDIR

该指令用于指定镜像的落脚点,即:启动镜像后初始进入的目次,若是没有设置装备摆设,则默认是

/

好比:

[root@localhost test]# docker run -it mycentos_test02 [root@9c958bd3830f /]#

启动镜像后起首进入的即是

/

目次,但若是设置装备摆设了WORKDIR:

FROM centos WORKDIR /opt/work

构建镜像:

docker build -t mycentos_test05 .

启动镜像:

[root@localhost test]# docker run -it mycentos_test05 [root@37f177c1e546 work]# pwd /opt/work

需要留意,只要设置装备摆设了WORKDIR,无论你有没有在后续的指令中利用到它,WORKDIR设置装备摆设的目次是必然会在镜像中被创建的。

ENV

该指令用于为镜像设置情况变量,好比:

FROM centos ENV name centos WORKDIR /$name

在那里设置装备摆设了一个情况变量name,值为centos,并在WORKDIR指令中引用了该变量,所以通过该文件构建出来的镜像在启动时就会间接进入/centos目次,验证一下:

[root@localhost test]# docker build -t mycentos_test06 . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM centos ---> 300e315adb2f Step 2/3 : ENV name centos ---> Running in 4c272c71fc62 Removing intermediate container 4c272c71fc62 ---> 0c00112be488 Step 3/3 : WORKDIR /$name ---> Running in 19bb2ad9d3cb Removing intermediate container 19bb2ad9d3cb ---> d7405fa45cb0 Successfully built d7405fa45cb0 Successfully tagged mycentos_test06:latest [root@localhost test]# docker run -it mycentos_test06 [root@0a505138f024 centos]# pwd /centos VOLUME

该指令用于定义容器运行时能够挂载到宿主机的目次,修改一下Dockerfile:

FROM centos ENV name centos WORKDIR /$name VOLUME /$name

此时设置装备摆设了VOLUME,值为

/$name

则容器中的/centos目次就允许被外部挂载。 构建镜像:

docker build -t mycentos_test07 .

然后在启动镜像的同时挂载一下数据卷:

docker run -it -v /opt/centos:/centos mycentos_test07

如许两个目次就实现了共享,此时在/opt/centos目次下的操做城市被同步到容器中的/centos目次:

[root@localhost test]# cd /opt/centos/ [root@localhost centos]# touch test [root@localhost centos]# docker run -it -v /opt/centos:/centos mycentos_test07 [root@37450c713b08 centos]# ls test ADD

该指令用于将context目次中指定的文件复造到镜像的指令目次中去,那么起首我们就要晓得何为context目次。 context目次意为上下文目次,指的是Dockerfile文件所在的目次,好比:

[root@localhost opt]# ll total 262144 drwx--x--x. 4 root root 28 Jun 18 11:27 containerd -rw-r--r--. 1 root root 268435456 Jun 23 15:46 disk.bin -rw-r--r--. 1 root root 0 Jul 23 07:08 Dockerfile drwxr-xr-x. 3 root root 25 Jul 22 12:45 javaproject drwxr-xr-x. 8 10143 10143 273 Apr 7 19:26 jdk1.8.0_291 drwxr-xr-x. 2 root root 24 Jul 23 07:04 test drwxr-xr-x. 8 root root 160 Jul 5 12:52 zookeeper-3.5.7

若是此时Dockerfile文件处在/opt目次下,则context目次则为/opt目次,因为DockerServer会将context目次中的所有文件,包罗子目次及其子文件停止打包构建,所以那也是为什么我们一起头创建一个空的文件夹,并将Dockerfile放在此中,因为文件过多会招致构建速度变慢。 修改Dockerfile:

FROM centos ENV name centos WORKDIR /$name VOLUME /$name ADD test.txt /

在Dockerfile所在目次下有一个test.txt,如今要将其复造到容器中的

/

目次下,构建镜像:

docker build -t mycentos_test08 .

启动镜像:

[root@localhost test]# docker run -it mycentos_test08 [root@184a8824b583 centos]# cd / [root@184a8824b583 /]# ls -l | grep test -rw-r--r--. 1 root root 0 Jul 23 07:25 test.txt

若是想修改添加到容器后的文件名,则间接指命名字即可:

ADD test.txt /ntest.txt

ADD不只可以添加文件、目次,还可以添加一个url,好比:

ADD http://www.baidu.com /test.html

则启动构建后的镜像时,便会在

/

目次下创建test.html文件,并将拜候http://www.baidu.com所得到的响应成果写入该文件。

构建一个SpringBoot应用的镜像

大要领会Dockerfile中的一些指令之后,我们就能够通过它来构建一个SpringBoot应用的镜像了,所以起首来编写一个十分简单的SpringBoot应用:

@RestController public class TestController { @GetMapping("/testMethod") public String testMethod(){ return "success"; } }

创建一个控造器用于测试即可,然后将应用打成一个jar包,利用maven插件即可停止打包,指令如下:

mvn clean package

将得到的jar包上传至办事器:

[root@localhost ~]# cd /opt/test/ [root@localhost test]# ls -l | grep .jar -rw-r--r--. 1 root root 16568766 Jul 23 07:56 SpringBootDemo-0.0.1-SNAPSHOT.jar

编写Dockerfile:

FROM openjdk:8 # 指定根底镜像 WORKDIR /test # 指定工做目次 ADD SpringBootDemo-0.0.1-SNAPSHOT.jar /test # 将jar包复造到容器中 EXPOSE 8080 # 向外表露8080端口 ENTRYPOINT ["java","-jar"] CMD ["SpringBootDemo-0.0.1-SNAPSHOT.jar"]

因为运行jar包需要JDK情况,所以间接利用openjdk8做为根底镜像即可,然后指定工做目次,接着将jar包复造到容器里的工做目次中,并向外表露8080端口,最初利用ENTRYPOINT和CMD指令结合构成jar包的运行号令。 如许就能够构建镜像了:

docker build -t springbootdemo .

运行镜像:

docker run -p 8080:8080 springbootdemo

镜像启动后会主动运行jar包,此时外部主机就能够拜候到pringBoot应用了:

上传镜像到办事器

那里以阿里云为例,我们将适才构建的镜像上传至阿里云的镜像办事器中,起首登录阿里云,搜刮

容器镜像办事

并开通:

开通后进入办理控造台,点击左侧的定名空间,创建一个定名空间:

然后点击左侧的镜像仓库,创建一个镜像仓库:

选择刚刚创建的定名空间,并填写仓库名称:

点击下一步后选择当地仓库:

点击创建镜像仓库,完成后能够看到阿里云供给的操做指南,我们照着操做指南停止操做即可。

起首登录到阿里云:

docker login --username=取个名字好困难a registry.cn-hangzhou.aliyuncs.com

然后会要求输入密码,密码在开通容器镜像办事的时候就会让你设置,若是没有设置密码,也能够在页面右侧的新手引导中点击拜候凭证停止设置:

然后为镜像设置tag:

docker tag 8d4d7be1d926 registry.cn-hangzhou.aliyuncs.com/test_respository/springbootdemo:1.0.0

那里有两处处所需要设置(ImageId和版本号):

docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/test_respository/springbootdemo:[镜像版本号]

此中ImageId为镜像的id,通过

docker images

即可查询到,镜像版本号能够随意填写。 最初将镜像推送到办事器上:

docker push registry.cn-hangzhou.aliyuncs.com/test_respository/springbootdemo:1.0.0

此时点击镜像版本查看一下镜像能否胜利上传了:

接下来测试一下拉取功用,起首删除掉之前构建的镜像:

docker rmi springbootdemo

施行指令停止拉取:

docker push registry.cn-hangzhou.aliyuncs.com/test_respository/springbootdemo:1.0.0 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry.cn-hangzhou.aliyuncs.com/test_respository/springbootdemo 1.0.0 8d4d7be1d926 41 minutes ago 531MB openjdk 8 f67a59e543c1 19 hours ago 514MB centos latest 300e315adb2f 7 months ago 209MB mycentos_test01 latest 300e315adb2f 7 months ago 209MB tomcat 8.0 ef6a7c98d192 2 years ago 356MB

拉取下来的镜像就能够启动了,只不外镜像的名字变得比力长了:

docker run -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/test_respository/springbootdemo:1.0.0

0
回帖 返回旅游

Dockerfile 若何编写与构建? 期待您的回复!

取消
载入表情清单……
载入颜色清单……
插入网络图片

取消确定

图片上传中
编辑器信息
提示信息