深入理解Docker——DockerFile语法实践和DockerHub提交

mac2026-04-14  2

文章目录

DockerFile语法实践FROMLABEL容器命令:RUN\CMD\ENTRYPOINTRUN命令格式:Shell 和 ExecCMDENTRYPOINT WORKDIRADD和COPYENVVOLUMEEXPOSE DockerHub使用DockerFile 实战:将Springboot打包成为Image 更多语法可以参考 Dockerfile Reference

DockerFile语法实践

FROM

FROM scratch #没有base,从头制作 FROM centos FROM ubuntu:14.04

FROM指定了base Image,所以尽量使用官方的Image作为一个Base Image。

LABEL

LABEL maintainer="leesanghyuk@gmail.com" LABEL version="1.0" LABEL description="based on centos"

LABEL定义了Image的Metadata,LABEL有点像代码里面的注释。

容器命令:RUN\CMD\ENTRYPOINT

RUN

RUN yum update && yum install -y vim\ python-dev RUN apt-get update && apt-get install -y perl\ pwgen --no-install-reconmmends && rm -rf\ /var/lib/apt/lists/*

RUN的最佳实践是为了避免无用分层,尽量合并多条命令到一行,通过&&和\。

命令格式:Shell 和 Exec

Shell格式很好理解,就是一个完整的命令,默认是通过Shell执行命令。 Exec格式,第一个就是运行的命令,后面接它的参数,比如RUN ["apt-get","install","-y","vim"],运行的命令是apt-get,这个命令的参数是,"install","-y","vim"三个。

我们来看下面一个例子:

FROM centos ENV CREATOR leesanghyuk ENTRYPOINT echo hello,${CREATOR}

FROM centos ENV CREATOR leesanghyuk ENTRYPOINT ["/bin/echo"," hello,${CREATOR}"]

构建并运行:

root@kexin228-lab:~/centos-vim-dir# docker build -t kexin228/centos-shell . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM centos ---> 0f3e07c0138f Step 2/3 : ENV CREATOR leesanghyuk ---> Running in 0d6cc1457b63 Removing intermediate container 0d6cc1457b63 ---> 8a270f4d3b52 Step 3/3 : ENTRYPOINT echo hello,${CREATOR} ---> Running in c1f7b1b25ff2 Removing intermediate container c1f7b1b25ff2 ---> 7527e5e5d131 Successfully built 7527e5e5d131 Successfully tagged kexin228/centos-shell:latest root@kexin228-lab:~/centos-vim-dir# docker run -it kexin228/centos-shell hello,leesanghyuk root@kexin228-lab:~/centos-vim-dir# docker build -t kexin228/centos-exec . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM centos ---> 0f3e07c0138f Step 2/3 : ENV CREATOR leesanghyuk ---> Using cache ---> 8a270f4d3b52 Step 3/3 : ENTRYPOINT ["/bin/echo"," hello,${CREATOR}"] ---> Running in 3a49d4ae8627 Removing intermediate container 3a49d4ae8627 ---> d600e1fd8a90 Successfully built d600e1fd8a90 Successfully tagged kexin228/centos-exec:latest root@kexin228-lab:~/centos-vim-dir# docker run -it kexin228/centos-exec hello,${CREATOR}

可以发现Shell格式构建的,输出取到了ENV的值,而EXEC格式的没有(我们执行的是echo这个命令,并不是一个shell)。 可以通过ENTRYPOINT ["/bin/bash","-c","echo hello,${CREATOR}"]取到ENV。

CMD

CMD是容器启动时默认执行的命令,且如果又多个CMD,只有最后一个会执行。 我们使用docker run -it [image] /bin/bash这里的/bin/bash实际上就是一个CMD命令,相当于我们执行了多个CMD命令,而最后一个CMD命令会被执行,也就是/bin/bash会被执行,dockerfile中定义的CMD将会被忽略。

ENTRYPOINT

ENTRYPOINT也是容器启动时执行的,它让容器以应用程序或者服务的形式运行。与CMD不同的是,它不会被忽略,一定会被执行。

一般来说,我们通常是写一个shell脚本作为entrypoint。

COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 27017 CMD["mongod"]

WORKDIR

WORKDIR /root WORKDIR /test #如果这个目录,没有会自动创建 WORKDIR demo RUN pwd #输出结果应该是/test/demo

workdir是设定当前工作目录的,所以我们要用WORKDIR不要使用RUN cd,并且尽量使用绝对目录。

ADD和COPY

ADD hello / ADD test.tar.gz / #添加到根目录并解压 WORKDIR /root ADD hello test/ # /root/test/hello WORKDIR /root COPY hello test/

ADD和COPY是把文件添加到某个目录中,他们的区别是ADD不光可以添加,还可以解压缩。大部分情况下,COPY要优先于ADD使用,添加远程文件/目录,使用RUNcurl或者wget命令。

ENV

ENV MYSQL_VERSION 5.6 #设置常量 RUN apt-get install -y mysql-server=${MYSQL_VERSION} #引用常量

ENV就是设置一个常量,可以增加一个可维护性。

VOLUME

外挂Volume,使得数据不会随着容器的消失而消失。 显示容器挂载的目录的命令:docker inspect [image] |grep -A 8 Mounts

EXPOSE

暴露容器端口。

DockerHub使用

这里展示提交我们的镜像到dockerhub上的过程。 登陆docker hub.

root@kexin228-lab:~/centos-vim-dir# docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username:leesanghyuk Password: Login Succeeded

创建一个hello-world的dockerfile,创建镜像。过程略。 push镜像。

root@kexin228-lab:~/centos-vim-dir# docker push kexin228/hello-world The push refers to repository [docker.io/kexin228/hello-world] af0b15c8625b: Preparing denied: requested access to the resource is denied

上传出错原因:tag里面必须包含用户名,所以把kexin228改成leesanghyuk就行了。 重新命名:

root@kexin228-lab:~/centos-vim-dir# docker tag kexin228/hello-world leesanghyuk/hello-world 再次push即可。

官网上即可查看。

DockerFile 实战:将Springboot打包成为Image

写一个Demo,打包成jar包(maven package打包,如下图所示)。

查看构建好的jar文件:

LeesangHyuk:SpringbootToImage leesanghyuk$ cd target LeesangHyuk:target leesanghyuk$ ls classes generated-sources maven-status demo-0.0.1-SNAPSHOT.jar generated-test-sources surefire-reports demo-0.0.1-SNAPSHOT.jar.original maven-archiver test-classes #启动 LeesangHyuk:target leesanghyuk$ java -jar demo-0.0.1-SNAPSHOT.jar

访问端口,说明jar包打包正确。

接下来在target目录中创建dockerfile:

# touch dockerfile FROM java:8 LABEL author=leesanghyuk EXPOSE 8080 VOLUME /tmp ADD demo-0.0.1-SNAPSHOT.jar /demo.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/demo.jar"]

接下来又两种方法来构建:


方法一: 通过docker push

使用docker build -t在本地打包镜像。

将镜像用docker push发布到docker hub上即可。


方法二:通过github和docker hub自动构建。

在个人accounts里面设置关联github。 创建docker hub 的registry 在docker registry中设置automated builds(主要是设置build path) 这里build Context 要设置成为dockerfile的位置,这里是根目录,所以把项目的dockerfile移动到根目录。

然后使用git push即可自动生成镜像。

LeesangHyuk:SpringbootToImage leesanghyuk$ git add . LeesangHyuk:SpringbootToImage leesanghyuk$ git commit -m "update Dockerfile" [master 7151851] update Dockerfile 1 file changed, 2 insertions(+) LeesangHyuk:SpringbootToImage leesanghyuk$ git push To github.com:BonjourMondo/SpringbootToImage.git f2bc3d5..7151851 master -> master

可以看到已经开始build了,但是免费版build(出错)容易找不到dockerfile,这里需要耐心等待。另外,build是官方自己来build,不需要我们自己build。

最新回复(0)