Dockerfile docker
FROM 指定基础镜像
FROM centos:centos7
MAINTAINER 指定作者信息
MAINTAINER "qiyang <qiyang@email.com>"
LABEL 为一个镜像指定元数据,包括作者信息等
LABEL <key>=<value> <key>=<value> LABEL maintainer="qiyang <qiyang@email.com>"
RUN 一个RUN命令即构建一层镜像。
RUN buildDeps='gcc libc6-dev make' \ #像shell一样可以定义变量 && yum install -y $buildDeps \ && mkdir /tmp
COPY 源路径 镜像中的位置 ,就是把dockerfile上下文位置的文件拷贝到镜像中。
可以用Go语言的通配符
注意:将文件拷贝到目录必须用斜杠“/”结尾。
COPY hom* /usr/local/app/ COPY hom?.txt /usr/local/app/ COPY file1.txt file2.txt /app/data/
ADD 高级复制目录
可以下载文件,下载的文件位600权限,调整权限或修改文件都需要使用RUN增加一层。如果是gzip2,bzip2、xz 的情况下会自动解压缩这个文件,可以下载远程文件。建议只有在需要解压的的情况下使用ADD,其他情况下都是用COPY。
自动解压:
ADD demo.tar.gz /data/
下载远程文件:
ADD chuxiangyi.com/index.html /data/
CMD 用于指定容器默认主进程的启动命令。
格式一(shell):CMD command
格式二(exec):CMD ["command","param","param"...]
格式三:CMD ["param","param"...] 这些参数传给 ENTRYPOINT 作为你 ENTRYPOINT 命令的参数。
如默认情况下centos镜像默认执行的命令是/bin/bash,我们可以使用CMD命令改变默认执行的命令。
docker run --name ceonts1 -it centos cat /etc/centos-release
比如说制作centos镜像最后的CMD为:CMD ["/bin/sh","-c"],在docker run 的时候后面的 cat /etc/centos-release 替换的就是CMD括号内的命令。
格式一与格式二的相同之处:CMD echo $HOME 会被解析成 CMD ["/bin/sh","-c","echo $Home"] ,其中 -c 的意思为从字符串中获取命令。
运行nginx命令:使用service启动nginx是错误的,因为使用service命令是让进程运行在后台。下面是正确的做法。
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT 同CMD。
格式一(shell):ENTRYPOINT command
格式二(exec):ENTRYPOINT ["command","param","param"...]
格式三:ENTRYPOINT CMD,使用方法如下:
CMD ["param","param"...] ENTRYPOINT command
CMD 里面的参数传给 ENTRYPOINT 作为 ENTRYPOINT 命令的参数。也就是说当使用 ENTRYPOINT 命令时 CMD 命令的意义就是为 ENTRYPOINT 传参。
CMD ["-f","-h","/data"] #传参给下面的命令 ENTRYPOINT ["bin/httpd"]
如上面这个示例,实际运行的指令是 /bin/httpd -h /data 。
要想在docker run时替换默认的命令,要使用 --entrypoint 参数。
ENTRYPOINT的作用:
在命令行使用 docker run name 时,如果后面有参数如:docker run name -h 这个后面的 -h 就可以作为参数传给 ENTRYPOINT。这样就可以在镜像制作好之后改变镜像默认运行的参数。
在运行默认程序时做一些初始化的工作。如下面的例子,默认情况下-a作为init.sh脚本的参数,可以在运行脚本的时候传入其他参数代替-a这个默认参数。
ENTRYPOINT ["init.sh"] CMD ["-a"]
示例:
FROM busybox:latest MAINTAINER "qiyang" RUN mkdir -p /data1/ && mkdir -p /data2/ && echo 'data1' > /data1/index.html && echo 'data2' > /data2/index.html ENTRYPOINT ["/bin/httpd","-f","-h"] CMD ["/data1/"]
docker build -t test:1.1 .
docker run --name b1 -it test:1.1 /data1
docker run --name b1 -it test:1.1 /data2
如上所示,当传入不同的目录/data1 或/data2 时就会使用不同的文档目录。
ENV 设置环境变量,同shell。这个变量不能再CMD和ENTRYPOINT中使用。
ENV VERSION=1.0 DEBUG=on \ NAME="hello world" ENV NAME hello
ARG 同ENV,不同的是设置的环境变量在实际的容器中不会保留。一个ARG只能设置一个键值对。
可以在创建镜像时修改ARG的值。如下示例,后面的version就是要修改的值。
docker build -t test:1.1 --build-arg version=1.2
VOLUME 定义匿名卷,这个卷指定的是镜像内的位置而不是宿主机的位置。
VOLUME path
VOLUME ["path","path"]
在运行容器时可以覆盖这个默认设置 docker run --name b1 -d -v /mydata:/data mysql:latest
volume 是用来挂载宿主机上的目录到容器的,VOLUME 只能够指定容器中目录的位置,没办法指定宿主机的目录位置,只能在docker run 的时候使用 -v 参数来指定。
因为只能指定容器中的目录位置,那么宿主机的位置在哪里了呢,使用命令 docker inspect -f {{.Mounts}} container_name 来查看。
需要注意的是,如果在创建容器时没有使用 --rm 参数,volume是不会被删除的,需要使用 docker container rm -v container_name 来参数容器的同时一起删除 Volume。如果这两种方法都没有使用那么可能有很多 Volume 任然占用着空间。
EXPOSE 声明端口,使用 -P 可以暴露默认端口。
可以在运行容器时使用-p来替换 docker run --name web1 -d -p 8080:80 nginx:latest
-p <宿主IP>:<宿主端口>:<容器端口>
EXPOSE 在 Dockerfile 中的使用:
EXPOSE [port]:[protocol] [port]:[protocol] ...
EXPOSE 80/tcp 80/udp 443/tcp EXPOSE 80
WORKDIR 指定工作目录
这个目录必须存在,可以指定多次,影响到后面的层,指定的这个位置是容器内的位置,可用ENV定义。
WORKDIR /usr/local/src/
USER 指定当前用户
切换到指定用户,影响到后面的层,这个用户必须存在。
RUN groupadd -r redis && useradd -r -g redis redis USER redis RUN [ "redis-server" ]
HEALTHCHECK 健康检查
HEALTHCHECK [选项] CMD
HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常。如果程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了,通过该指令指定一行命令,用这行命令来判断容器主进程的服务状态是否还正常。
HEALTHCHECK 只可以出现一次。
--interval=<间隔>
--timeout=<时长>
--retries=<次数>
命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 :保留,不要使用这个值。
FROM nginx RUN apt-get update && apt-get install -y curl && rm -rf /var/lib /apt/lists/* HEALTHCHECK --interval=5s --timeout=3s \ CMD curl -fs http://localhost/ || exit 1
使用 docker container ls -a 查看状态:
3 seconds ago Up 2 seconds (health: starting) 80/tcp, 443/tcp web
最初的状态为 (health:starting)
健康状态:healthy
不健康状态:unhealthy
健康查询的输出法可以用 docker inspect 来查看。
docker inspect --format '{{json .State.Health}}' web | python -m json.tool
ONBUILD 以当前镜像作为基础制作的镜像才会被执行。
ONBUILD <其它指令> 其他指令为COPY、RUN等。
将某个镜像作为基础镜像时,以这个镜像构建镜像时构建出来的镜像可以继承基础镜像上的变化。
基础镜像的Dockerfile,命名为my-node
FROM node:slim RUN "mkdir /app" WORKDIR /app ONBUILD COPY ./package.json /app ONBUILD RUN [ "npm", "install" ] ONBUILD COPY . /app/ CMD [ "npm", "start" ]
官方写好的常用镜像:
github.com/docker-library
时区问题解决:
FROM centos:7 RUN yum install -y tzdata ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone CMD ["date"]
常见示例:
Java Dockerfile:
FROM centos:7 ADD jdk-8u291-linux-x64.tar.gz /opt/ # 或 # ADD jdk-11.0.12_linux-x64_bin.tar.gz /opt/ ENV JAVA_HOME /opt/jdk1.8.0_291 # 或 # ENV JAVA_HOME /opt/jdk-11.0.12 ENV PATH $JAVA_HOME/bin:$PATH CMD ["java", "-version"]