文章目录
更多语法可以参考 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
使用,添加远程文件/目录,使用RUN
curl或者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。