最近公司项目须要使用docker进行项目部署,现记录下这段时间的学习内容,本章主要记录dockerfile来自定义镜像。固然咱们还能够用commit经过容器来自定义镜像,可是我此次基本都是用dockerfile来生成镜像,commit等之后有用到再做记录。java
FROM 指定基础镜像,放在第一行,其格式为:mysql
1 #语法: 2 FROM <image> 3 FROM <image>:<tag> 4 FROM <image>:<digest>
若想构建一个最小的镜像,不想基于其余任何镜像时。可直接linux
1 FROM scratch
MAINTAINER指令容许你设置生成这个镜像的做者。web
1 MAINTAINER lzq <xxx@xx.com>
也可使用LABEL设置镜像相关信息redis
1 LABEL author="做者:xxx" 2 LABEL version="版本:v0.1" 3 LABEL desc="说明:test"
要查看时,可使用docker inspect 镜像名或id 进行查看sql
ENV 设置环境变量,如java_home等。docker
1 ENV <key> <value> 2 ENV <key>=<value> ...
VOLUME 定义匿名卷,在咱们运行容器时,有些数据是须要被持久化保存的,好比mysql容器中的数据,tomcat容器中的logs日志等,可是通常来讲容器内的数据会随着容器的删除而消失,就算是用相同镜像再去生成容器,运行时产生的数据也不会存在。因此当咱们须要对某些数据进行持久化时,能够在生成容器时加上【-v 卷名或主机目录:容器目录 】的参数来对容器某个或多个目录进行挂载,这样的话就算以后容器被删除,其被挂载的目录数据仍会存在于主机之中,并且挂载以后对卷或主机目录的修改会同步到容器对应目录中,反之亦然。而若是挂载的主机卷或者目录一开始就存在数据,则不管容器对应目录内有无数据,都会被隐藏,显示的是挂载主机卷或目录存在的数据。通常来讲-v参数若是没有指定卷名或者主机目录,只指定容器目录的话,那么docker会自动为容器生成一个匿名卷,这样的话效果跟在dockerfile中用VOLUME命令是同样的,但每次都靠执行run命令生成容器时去添加-v参数的话有时会遗漏。因此咱们能够在dockerfile文件使用VOLUME命令先定义匿名卷,对须要持久化的目录进行挂载,这样的话若是生成容器时忘了使用-v参数去挂载容器重要目录,docker也会生成匿名卷将数据保存。而若是在run时使用-v参数对dockerfile中使用VOLUME挂载的目录进行定义时(如指定卷名或者主机目录),则docker不会生成匿名卷,而是根据当前指定的卷名或主机目录对容器目录进行挂载。shell
例如这是一份docekrfile文件:windows
1 FROM centos:latest 2 RUN groupadd -r redis && useradd -r -g redis redis 3 RUN yum -y update && yum -y install epel-release && yum -y install redis && yum -y install net-tools 4 5 RUN mkdir -p /config && chown -R redis:redis /config 6 7 8 VOLUME /share/data #声明容器中/share/data为匿名卷 9 10 11 EXPOSE 6379
那么使用该Dockerfile构建镜像的为centos
1 #docker build -t image-redis //构建镜像image-redis 2 ...... 3 #docker run -itd -name redis1 -v /data:/share/data image-redis //运行一个容器而且将当前机器的/data目录绑定到容器的匿名卷中 4 ..... 5 #docker run -itd -name redis2 image-redis //运行一个容器可是不绑定目录到容器的匿名卷,这时候在/var/lib/docker/volumes(不一样版本目录不同)中就会建立一个目录绑定匿名卷 6 .....
删除数据卷
数据卷
是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷
,而且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷
。若是须要在删除容器的同时移除数据卷。能够在删除容器的时候使用 docker rm -v
这个命令。
数据卷可能会占据不少空间,可使用如下命令清理掉没有容器使用的数据卷
。谨慎操做,这须要你确认如今暂时没有使用
数据卷在之后也不会再使用,里面也没有有价值的数据。
1 docker volume prune
COPY 复制文件,主要就是构建镜像时,进行拷贝文件到镜像的指定路径下,格式为:
1 COPY <源路径>... <目标路径> 2 COPY ["<源路径1>",... "<目标路径>"]
ADD 更高级的复制文件,ADD
指令和 COPY
的格式和性质基本一致。可是在 COPY
基础上增长了一些功能。好比<源路径>
能够是一个 URL
,这种状况下,Docker
引擎会试图去下载这个连接的文件放到<目标路径>
去,而若是原路径是个压缩包的话,ADD会在复制完毕后在目标目录将文件进行解压。
1 ADD jdk-8u45-linux-x64.tar.gz /usr/local
EXPOSE 设置监听端口,为镜像设置监听端口,容器运行时会监听改端口,格式为:
1 EXPOSE <port> [<port>/<protocol>...] 2 EXPOSE 80 3 EXPOSE 80/udp
RUN 执行命令,在镜像的构建过程当中执行特定的命令,并生成一个中间镜像。格式:
1 RUN <command> 2 或者 3 RUN ["executable", "param1", "param2"]
这也是很经常使用的一个功能了。
第一种后边直接跟shell命令
第二种是相似于函数调用。
可将executable
理解成为可执行文件,后面就是两个参数。
两种写法比对:
1 RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME 2 RUN ["/bin/bash", "-c", "echo hello"]
注意:多行命令不要写多个RUN
,缘由是Dockerfile
中每个指令都会创建一层.多少个RUN就构建了多少层镜像,会形成镜像的臃肿、多层,不只仅增长了构件部署的时间,还容易出错。
RUN
书写时的换行符是\
CMD 启动时命令,功能为容器启动时要运行的命令,有三种写法:
1 1. CMD ["executable","param1","param2"] 2 2. CMD ["param1","param2"] 3 3. CMD command param1 param2
第三种比较好理解了,就时shell
这种执行方式和写法,第一种和第二种其实都是可执行文件加上参数的形式:
举例说明两种写法:
1 CMD [ "sh", "-c", "echo $HOME" ] 2 CMD [ "echo", "$HOME" ]
补充细节:这里边包括参数的必定要用双引号,就是双引号"
,不能是单引号。千万不能写成单引号
。缘由是参数传递后,docker
解析的是一个JSON array
。
ENTRYPOINT 启动默认命令,ENTRYPOINT
用于给容器配置一个可执行程序。也就是说,每次使用镜像建立容器时,经过 ENTRYPOINT
指定的程序都会被设置为默认程序。ENTRYPOINT
有如下两种形式:
1 ENTRYPOINT ["executable", "param1", "param2"] 2 ENTRYPOINT command param1 param2
ENTRYPOINT
与 CMD
很是相似,不一样的是经过docker run
执行的命令不会覆盖 ENTRYPOINT
,而docker run
命令中指定的任何参数,都会被当作参数再次传递给ENTRYPOINT
。Dockerfile
中只容许有一个 ENTRYPOINT
命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT
指令。docker run
运行容器时指定的参数都会被传递给ENTRYPOINT
,且会覆盖 CMD 命令指定的参数。如,执行docker run <image> -d
时,-d
参数将被传递给入口点。
也能够通过docker run --entrypoint
重写 ENTRYPOINT
入口点。
WORKDIR 指定工做目录,用于在容器内设置一个工做目录:
1 WORKDIR /opt/docker/workdir
经过WORKDIR
设置工做目录后,Dockerfile
中其后的命令RUN
、CMD
、ENTRYPOINT
、ADD
、COPY
等命令都会在该目录下执行。
USER 指定当前用户,用于指定运行镜像所使用的用户:
1 USER lzq
使用USER
指定用户后,Dockerfile
中其后的命令RUN
、CMD
、ENTRYPOINT
都将使用该用户。镜像构建完成后,经过docker run
运行容器时,能够经过-u
参数来覆盖所指定的用户。
经过上面的命令咱们能够编写一个dockerfile来自定义咱们的镜像,如今咱们来构建一个tomcat镜像,首先咱们得准备jdk和tomcat,咱们能够在dockerfile中去下载,但我这里已经下载了下来了
dockerfile当前目录:
dockerfile内容:
该文件内容定义了:
一、使用了centos做为基础镜像
二、复制并解压了jdk,定义了JAVA环境变量
三、复制并解压了tomcat,定义了CATALINA_HOME
四、设置8080监听接口
五、定义tomcat的webapps目录为匿名卷
六、复制web文件夹中的文件到容器webapps目录中
七、设置tomcat的bin目录为工做目录
八、设置容器启动时默认启动tomcat
接下来咱们用这个文件生成一个镜像:
1 docker build -t tomcat .
这样就生成了一个自定义tomcat镜像,咱们能够运行docker images查看
可见tomcat镜像已经生成,接下来咱们用该镜像生成一个容器:
1 docker run -itd -p 9000:8080 --name tomcat tomcat
容器已经生成,咱们能够输入docker ps 查看正在运行的容器:
可见容器已经在运行,此时咱们打开浏览器,输入ip:9000并回车,能够看到
出现如上页面,说明咱们容器中的tomcat也随着容器启动而启动了。