docker使用小记3-dockerfile自定义镜像

最近公司项目须要使用docker进行项目部署,现记录下这段时间的学习内容,本章主要记录dockerfile来自定义镜像。固然咱们还能够用commit经过容器来自定义镜像,可是我此次基本都是用dockerfile来生成镜像,commit等之后有用到再做记录。java

1、dockerfile命令

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命令

  • 在linux操做系统上默认 /bin/sh -c
  • 在windows操做系统上默认 cmd /S /C

第二种是相似于函数调用。

可将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命令中指定的任何参数,都会被当作参数再次传递给ENTRYPOINTDockerfile 中只容许有一个 ENTRYPOINT 命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT 指令。
docker run运行容器时指定的参数都会被传递给ENTRYPOINT,且会覆盖 CMD 命令指定的参数。如,执行docker run <image> -d时,-d 参数将被传递给入口点。
也能够通过docker run --entrypoint重写 ENTRYPOINT 入口点。

 

WORKDIR 指定工做目录,用于在容器内设置一个工做目录:

1 WORKDIR /opt/docker/workdir

经过WORKDIR设置工做目录后,Dockerfile 中其后的命令RUNCMDENTRYPOINTADDCOPY等命令都会在该目录下执行。

 

USER 指定当前用户,用于指定运行镜像所使用的用户:

1 USER lzq

使用USER指定用户后,Dockerfile 中其后的命令RUNCMDENTRYPOINT都将使用该用户。镜像构建完成后,经过docker run运行容器时,能够经过-u参数来覆盖所指定的用户。

 

2、使用dockerfile构建自定义镜像

经过上面的命令咱们能够编写一个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也随着容器启动而启动了。

 

参考资料:https://blog.lqdev.cn/2018/08/04/docker/docker-five/

     https://blog.csdn.net/fangford/article/details/88873104

相关文章
相关标签/搜索