Dockfile是一个用于编写docker镜像生成过程的文件,其有特定的语法。在一个文件夹中,如果有一个名字为Dockfile的文件,其内容满足语法要求,在这个文件夹路径下执行命令:docker build --tag name:tag .
,就可以按照描述构建一个镜像,name是镜像的名称,tag是镜像的版本或者是标签号。详情可以参考:https://docs.docker.com/engine/reference/builder/#usage
Dockerfile指令
Dockerfile的基本指令:FROM、LABEL、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD。
FROM
第一个指令必须是FROM了,其指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的latest标签,可以出现多次,如果需要在一个Dockerfile中构建多个镜像。
尽量使用官方的image作为base image
用法如下:
FROM scratch
FROM centos
FROM ubuntu:14.04
LABEL
描述镜像的信息,像代码的注释。用法如下:
LABEL maintainer="heqingliang@163.com"
LABEL version="1.0"
LABEL description="This is description"
RUN
RUN命令是一个常用的命令,执行完成之后会成为一个新的镜像,每执行一条RUN命令就是生成一层镜像。docker的镜像层是只读的,所以你如果第一句安装了软件,用完在后面一句删除是不可能的。所以这种情况要在一句RUN命令中完成,可以通过&符号连接多个RUN语句。
为了美观,复杂的RUN请用反斜杠换行,避免无用分层,合并多条命令成一行
用法如下:
RUN yum update && yum install -y vim python-dev
RUN apt-get update && apt-get install vim && rm -rf \
/var/lib/apt/lists/*
WORKDIR
用于设置工作目录,后续参数如果是相对路径,则会基于之前的命令指定的路径。如:
WORKDIR /test # 如果没有会自动创建test目录
WORKDIR demo
RUN pwd # 输出结果是/test/demo
path路径也可以是环境变量,比如有环境变量HOME=/home,WORKDIR $HOME/test
也就是/home/test。
ADD
复制本机文件、目录、远程文件,添加到指定的容器目录,支持GO的正则模糊匹配。路径是绝对路径,不存在会自动创建。如果源是一个目录,只会复制目录下的内容,目录本身不会复制。ADD命令会将复制的压缩文件夹自动解压,这也是与COPY命令最大的不同。
用法如下:
ADD hello /
ADD test.tar.gz / # 添加到根目录并解压缩
WORKDIR /root
ADD hello test/ # /root/test/hello
COPY
COPY除了不能自动解压,也不能复制网络文件。其它功能和ADD相同。添加远程文件或目录可以使用curl或者wget。
ENV
设置容器的环境变量,可以让其后面的RUN命令使用,容器运行的时候这个常量也会保留。
ENV MYSQL_VERSION 5.6 # 设置常量
RUN apt-get install -y mysql-server="${MYSQL_VERSION}"
EXPOSE
告诉Docker服务器容器对外映射的容器端口号,在docker run -p
的时候生效。
VOLUME
在主机上创建一个挂载,挂载到容器的指定路径。docker run -v
命令也能完成这个操作,而且更强大。这个命令不能指定主机的需要挂载到容器的文件夹路径。但docker run -v
可以,而且其还可以挂载数据容器。
CMD
设置容器启动后默认执行的命令和参数,如果docker run指定了其他的命令,CMD命令被忽略,如果定义了多个CMD,只有最后一个命令会执行。
如定义了以下的Dcokfile:
[heql@ubuntu dk]$ cat Dockerfile
FROM centos
ENV name Docker
CMD echo "hello $name"
build后只有用docker run image
,则会打印出:hello Docker,如果使用docker run -it image /bin/bash
,则不会打印。
ENTRYPOINT
和CMD命令一样,唯一的区别是不能被docker run
命令的执行命令覆盖,如果要覆盖需要带上选项–entrypoint,如果有多个选项,只有最后一个会生效。
FROM centos
ENV name Docker
ENTRYPOINT echo ["/bin/bash", "-c", "echo hello $name"]
ONBUILD
配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。意思就是,这个镜像创建后,如果其它镜像以这个镜像为基础,会先执行这个镜像的ONBUILD命令。
DCOKERFILE 例子
下面的python程序是一个使用flask框架编写的web的程序,文件命名为app.py:
1 | #!/usr/bin/env python3 |
使用下面的dockerfile,构建image:
FROM python
LABEL maintainer="heqingliang_gzus@163.com"
RUN pip install flask
COPY app.py /app/
WORKDIR /app
EXPOSE 5000
CMD ["python", "app.py"]
编译成功后,会生成相应的image:
[heql@ubuntu flask-demo]$ docker build -t heqingliang/flask-app .
[heql@ubuntu flask-demo]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
heqingliang/flask-app latest ddf38d204760 5 minutes ago
运行容器:
[heql@ubuntu flask-demo]$ docker run -d -p 5000:5000 --name=flask-app heqingliang/flask-app
79088d8fb9e39fedc9702e33fe7cc08a5c9a22322ffa9c7e1afab0680deafa47
[heql@ubuntu flask-demo]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
79088d8fb9e3 heqingliang/flask-app "python app.py" 6 seconds ago Up 4 seconds 0.0.0.0:5000->5000/tcp flask-app
在浏览器中输入http://127.0.0.1:5000/
,可以看到如下结果:
dockerfile命令行参数
如有以下程序,接收命令行程序:
1 |
|
编译hello.c
的程序:
gcc -static hello.c -o hello
使用下面的dockerfile,构建image:
FROM scratch
LABEL maintainer="heqingliang_gzus@163.com"
COPY hello /hello/
WORKDIR /hello
ENTRYPOINT ["./hello"]
CMD []
编译成功后,会生成相应的image:
[heql@ubuntu hello-world]$ docker build -t heqingliang/hello .
运行容器:
[heql@ubuntu hello-world]$ docker run heqingliang/hello
usage: <./hello args...>
[heql@ubuntu hello-world]$ docker run heqingliang/hello aa bb cc dd
argv[1]: aa
argv[2]: bb
argv[3]: cc
argv[4]: dd