Docker file
基本概念
是什么
Docker为我们提供的一个用于自定义构建镜像的配置文件,描述如何构建一个对象。
利用Docker提供的build命令,指定Dockerfile文件,就可以按照配置的内容将镜像构建出来。
为什么需要
- 作为开发者需要将自己开发好的项目打包成Docker镜像,便于后面直接作为Docker容器运行
- 作为运维人员需要构建更精简的基础设施服务镜像,满足公司的需求以及尽可能减少冗余的功能占用过多的资源
能干什么
- 可以自定义镜像内容
- 构建公共基础镜像减少其他镜像配置
- 开源程序的快速部署
- 实现企业内部项目的快速交付
构建镜像
commit(少用)
基于一个现有的容器,构建一个新的镜像
命令:
docker commit -a "作者名字" -m "描述信息" <容器名字> <构建的镜像名字>
例:
- 运行一个容器
docker run --rm -d -p 80:80 --name nginx_commit nginx
2. 进入容器,修改index文件
[root@localhost ~]# docker exec -it nginx_commit /bin/bash
root@0d4ac55e5959:/# cd /usr/share/nginx/html/
root@0d4ac55e5959:/usr/share/nginx/html# ls
50x.html index.html
root@0d4ac55e5959:/usr/share/nginx/html# echo '<h1>my nginx</h1>' > index.html
root@0d4ac55e5959:/usr/share/nginx/html# cat index.html
<h1>my nginx</h1>
root@0d4ac55e5959:/usr/share/nginx/html# exit
exit
3. 使用commit命令构建一个新的镜像
docker commit -a "xdn" -m "my nginx container" nginx_commit mynginx:1
4. 查看镜像
docker images
5. 验证,停止原先运行的容器,使用刚构建的镜像运行新的容器,浏览器访问
[root@localhost ~]# docker stop nginx_commit
nginx_commit
[root@localhost ~]# docker run --rm -d -p 80:80 --name mynginx mynginx:1
5ba7007969c6865cdf505ea632730962394268aab93062a0e470aafdac57fb63
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ba7007969c6 mynginx:1 "/docker-entrypoint.…" 7 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp mynginx
build(常用)
docker build -t <镜像名字:版本> <dockerfile路径>
# -t 表示要基于文件来构建镜像
Spring Boot镜像
例:
dockerfile内容:
# 关联基础镜像 => jdk
FROM openjdk:8
# 将项目 jar 包拷贝到容器中
ADD *.jar app.jar
#配置项目环境变量
ENV APP_OPTS=""
# JVM环境变量
ENV JVM_OPTS="-Duser.timezone=Asia/Shanghai -Xms128m -Xmx128m"
# 暴露端口
EXPOSE 8888
# 设置启动时的命令
ENTRYPOINT ["sh","-c","java $JVM_OPTS -jar /spp.jar $APP_OPT"]
Tomcat镜像
例:
FROM tomcat:9.0
WORKDIR /usr/local/tomcat/webapps
ADD *.war ROOT.war
ENTRTPOINT ["sh","-c","../bin/catalina.sh run"]
Nginx镜像
例:
# 设置基础镜像
FROM centos:7
# 维护者信息
MAINTAINER xdn<xiaodunan.cn>
# 加入构建镜像所需的文件
ADD pcre-8.38.tar.gz /usr/local/src
ADD nginx-1.14.2.tar.gz /usr/local/src
# 安装 c++ 源码编译的基础工具
RUN yum install -y wget gcc gcc-c++ make openssl-devel
# 创建 www 用户作为 nginx 启动用户
RUN useradd -s /sbin/nologin -M www #nologin指定用户不能登录
# 进入 nginx 解压后的源码目录
WORKDIR /usr/local/src/nginx-1.14.2
# nginx 编译安装
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www -with-http_ssl_module --with-http_stub_status_module --with-pcre=/usr/local/src/pcre-8.38
RUN make && make install
# 关闭 nginx 后台运行
RUN echo 'daemon off;' >> /usr/local/nginx/conf/nginx.conf
# 创建 nginx 命令快速访问的环境变量
# ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx (软连接方式)
ENV PATH /usr/local/nginx/sbin:$PATH #环境变量方式
# 用自己自定义的首页模板替换 nginx 原本的首页模板
ADD index.html /usr/local/nginx/html
# 暴露端口
EXPOSE 80
# 容器启动命令
CMD ["nginx"]
常用命令
FROM
指定当前镜像的基础镜像是什么
例:
FROM openjdk:8
MAINTAINER
描述镜像的作者,以及联系方式(可选)
例:
MAINTAINER xdn<xiaodunan.com>
LABEL(可选)
为镜像设置标签,一个Dockerfile中可以配置多个label
例:
LABEL version="1.0"
LABEL description="这是我的第一个Dockerfile"
ENV
设置容器的环境变量,可以设置多个
例:
ENV JAVA_ENV dev
ENV APP_NAME test-dockerfile
ENV JAVA_ENV=dev APP_NAME=test-dockerfile
# 两种语法的区别为第一种一次只能设置一个环境变量,第二种可以一次设置多个
RUN
在构建镜像时,需要执行的shell命令
例:
RUN ls -al
RUN mkdir /www/test/dockerfile/test
ADD
将主机中的指定文件复制到容器的目标位置,可以简单理解为cp
命令
例:
ADD /var/run/test /etc/hosts
#把主机的/var/run/test 拷贝到容器的/etc/hosts
ADD ["/var/run/test /","/etc/hosts"]
WORKDIR
设置容器的工作目录,如果该目录不存在会自己创建
例:
WORKDIR /app
#在设置完工作目录后执行pwd命令,打印的目录就是 /app,相当于cd命令
RUN pwd
VOLUME
镜像数据卷绑定,将主机中的指定目录挂载到容器中
例:
VOLUME ["/www/wolfcode.cn"]
EXPOSE
设置容器启动后要暴露的端口,仅仅只是在容器内暴露这个端口,跟主机没有关联
例:
EXPOSE 8080
CMD 和 ENTRYPOINT
选择其一即可,作用是描述镜像构建完成后,启动容器时默认执行的脚本,只能设置一次,如果写了多次则只有最后一次生效
区别:
- ENTRYPOINT不会被运行容器时所指定的命令所覆盖,而CMD会
- 如果同时设置了这两个指令,且CMD仅仅是选项而不是参数,CMD中的内容会作为ENTRYPOINT的参数(一般不这么做)
- 如果两个都是完整命令,那么只会执行最后一条
ENRYPOINT非json则以ENRYPOINT为准,如果ENRYPOINT和CMD都是JSON则ENRYPOINT+CMD拼接成shell
例:
CMD ping 127.0.0.1
CMD ["sh","-c","ping 127.0.0.1"] #sh 表示使用shell脚本
ENTRYPOINT ping 127.0.0.1
ENTRYPOINT ["sh","-c","ping 127.0.0.1"]
拓展指令
ARG
设置变量,在镜像中定义一个变量,当使用docker build
命令构建镜像时,带上--build-arg <name>=<value>
来指定参数值,如果该变量名在Dockerfile中不存在则会抛出一个警告。
语法
ARG <name>[=<default value>]
例:
ARG jdk=8
FROM openjdk:$jdk
USER
设置容器的用户,可以是用户名或UID,如果容器设置了以daemon
用户去运行,那么RUN.CMD和ENTRTPOINT
都会以这个用户运行,一定要先确定容器中有这个用户,并且拥有对应的操作权限。
语法:
USER <username>
USER <PID>
例:
RUN useradd wolfcode
#提前添加好用户
USER wolfcode
#表示后续容器中所有执行命令的操作都是以 wolfcode 这个用户操作的
ONBUILD
表示在构建镜像时做某操作,不过不对当前Dockerfile的镜像生效,而是对以当前Dockerfile镜像作为基础镜像的子镜像生效
语法:
ONBUILD [INSTRUCTION]
例:
当前镜像为A,设置了如下指令
ONBUILD RUN ls -al
镜像B:
FROM 镜像A
....
构建镜像B时,会执行la -al命令
STOPSIGNAL
STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。此信号可以是与内核的系统调用表中的位置匹配的有效无符号数。
HEALTHCHECK
容器健康状况检查,可以指定周期检查容器当前的健康状况,该命令只能出现一次,如果有多次则只有最后一次生效。
语法:
HEALTHCHECK [OPTION] CMD command
HEALTHCHECK NONE
#第一种:在容器内部按照指定周期运行指定命令来检测容器健康状况
#第二种:取消在基础镜像
返回参数:
0 健康
1 不健康
2 保留值,不确定成功还是失败
例:
健康检查,每隔10秒钟检查容器是否正常,每次不超过3秒钟,并且如果失败了,最多不能超过5次
HEALTHCHECK --interval=10 --timeout=3 --retries=5 CMD ps -ef | grep java || exit 1