在前面我们讲解了基于已有的镜像容器创建和基于本地模板导入两种方式来创建镜像, 在这里我们就来说说第三种创建镜像的方式. Dockerfile 是一个文本格式的配置文件, 我们可以通过 Dockerfile 快速创建自定义的镜像.
一, 基本结构
Dockerfile 是由多行命令语句组成的, 并且在文件中支持以 # 开始的注释行. 我们一般将 Dockerfile 文件分为四部分: 基础镜像信息, 维护者信息, 镜像操作指令和容器启动时执行指令. 其中, 第一行 (不包含注释行) 必须指定基于的基础镜像, 例如: FROM Ubuntu. 之后可以是维护者信息, 如: MAINTAINER gongziqi 14155830994@qq.com. 再往后可以是镜像的操作指令, 如:
- RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe">> /etc/apt/sources.list
- RUN apt-get update && apt-get install -y nginx
- RUN echo "\ndaemon off;">> /etc/nginx/nginx.conf
最后可以是容器启动时执行指令, 如: CMD /usr/sbin/nginx.
- # 0. 在 Ubuntu 镜像的基础上, 安装 inotify-tools/nginx/apache2/openssh-server 等, 创建新的 Nginx 镜像
- # Nginx
- # VERSION 1.0
- FROM Ubuntu
- MAINTAINER gongziqi 1415583094@qq.com
- RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
- # 1. 在 Ubuntu 镜像基础上, 安装 Firefox/vnc. 启动后, 用户可通过 5900 端口通过 vnc 方式使用 Firefox
- # Firefox over VNC
- # VERSION 1.0
- FROM Ubuntu
- RUN apt-get update && apt-get install -y x11vnc xvfb Firefox
- RUN mkdir ./.vnc
- RUN x11vnc -storepasswd 123456 ~/.vnc/passwd
- RUN bash -c 'echo"firefox">> /.bashrc'
- EXPOSE 5900
- CMD ["x11vnc","-forever","usepw","-create"]
二, 指令
1,FROM
语法为: FROM 或 FROM :. 若在同一个 Dockerfile 中创建多个镜像, 可以使用多个 FROM 即每个镜像一个.
2,MAINTAINER
语法: MAINTAINER , 用来指定维护者信息.
3,RUN
语法: RUN 或 RUN ["executable","param1","param2"]. 第一个将在 shell 终端中运行命令, 即 /bin/bash -c; 第二个则使用 exec 执行. 每条 RUN 指令将在当前镜像基础上执行指定指令, 并提交为新的镜像. 若命令行太长可以使用 \ 来换行书写.
4,CMD
支持三种方式:
CMD ["executable", "param1", "param2"], 使用 exec 执行, 推荐方式.
CMD command param1 param2, 在 /bin/sh 中执行, 提供给需要交互的应用.
CMD ["param1","param2"], 提供给 ENTRYPOINT 的默认参数.
指定启动容器时执行的命令, 每个 Dockerfile 只能由一条 CMD 命令. 若指定多条, 则只有最后一条有效. 若在启动容器时, 指定了运行的命令, 则 CMD 命令将会被覆盖.
5,EXPOSE
语法: EXPOSE [...], 如: EXPOSE 22 80 8443, 即告诉 Docker 服务器容器暴露的端口, 这些端口可供互联使用. 此时在容器启动中, 可使用 -P 来随机指定一个端口, 也可使用 -p 来指定具体的端口映射.
6,ENV
语法: ENV . 指定一个环境变量, 会被后面的 RUN 指令使用, 并在容器运行时保持. 如:
- ENV PG_MAJOR 9.3
- ENV PG_VERSION 9.3.4
- RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && ...
- ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
- 7,ADD
语法: ADD . 将复制指定的 src 到容器中的 desc. 其中, src 可以是 Dockerfile 所在目录的一个相对路径(文件 / 目录); 也可为一个 URL; 还可为一个 tar 文件.
8,COPY
语法: COPY . 复制本地主机的 src(Dockerfile 所在目录的相对路径)到容器中的 desc. 当目标路径不存在时, 将自动创建. 当使用本地目录为源目录时, 推荐使用 COPY, 不推荐 ADD.
9,ENTRYPOINT
语法: ENTRYPOINT ["executable","param1","param2"] 或 ENTRYPOINT command param1 param2(shell 中执行). 配置容器启动后执行的命令, 并且不可被 docker run 提供的参数覆盖. 每个 Dockerfile 只能有一个 ENTRYPOINT, 当指定多个时, 只有最后一个有效.
10,VOLUME
语法: VOLUME ["/data"]. 创建一个可以从本地主机或其他容器挂载的挂载点, 一般用来存放数据库和需要保持的数据等.
11,USER
语法: USER daemon. 指定运行容器时的用户名或 UID, 后续的 RUN 指令也会使用指定用户. 当服务不需要管理员权限时, 可通过该命令指定运行用户, 并且可以在之前创建所需要的用户. 如: RUN groupadd -r postgres && useradd -r -g postgres postgres. 若此时需要临时获取管理员权限, 则可使用 gosu, 不推荐使用 sudo.
12,WORKDIR
语法: WORKDIR /path/to/workdir. 为后续的 RUN,CMD,ENTRYPOINT 指令配置工作目录. 可使用多个 WORKDIR, 若后面的 WORKDIR 指定的是相对路径, 则是基于前一个 WORKDIR 指定的路径. 如:
- WORKDIR /a
- WORKDIR b
- WORKDIR c
- RUN pwd
- # 结果为:/a/b/c
- 13,ONBUILD
语法: ONBUILD [INSTRUCTION]. 配置当所创建的镜像作为其他新创建镜像的基础镜像时, 所执行的操作指令. 如: Dockerfile 使用如下的内容创建了镜像 image-A.
- [...]
- ONBUILD ADD . /App/src
- ONBUILD RUN /usr/local/bin/python-build --dir /App/src
- [...]
若基于 image-A 创建新的镜像时, 新的 Dockerfile 中使用 FROM image-A 指定基础镜像时, 会自动执行 ONBUILD 指令内容, 即等价于在 FROM 指令后添加了以上的两条指令. 在使用 ONBUILD 指令的镜像, 我们推荐在标签中注明, 如: Ruby:1.9-onbuild.
三, 创建镜像
在编写完 Dockerfile 之后, 可以通过 Docker build 命令来创建镜像. 语法为: docker build [选项] 路径, 即读取指定路径下的 Dockerfile, 并将该路径下所有内容发送给 Docker 服务端, 由服务端来创建镜像. 因此我们建议放置 Dockerfile 的目录为空目录. 若为非空目录, 希望忽略路径下的某些目录或文件, 可通过 .dockerignore 文件来配置.
- # 指定 Dockerfile 路径所在路径为 /tmp/docker_builder/, 希望生成镜像标签为 build_repo/first_image, # 在标签命名时需要注意, 所有字母必须为小写
- $ sudo docker build -t build_repo/first_image /tmp/docker_builder/
四, 一个实例
根据以上信息, 我们来自己创建一个 Nginx 镜像.
- # 0. 创建 Dockerfile 所在目录
- $ sudo mkdir /opt/tmp_dockerbuilder
- # 1. 创建 Dockerfile 文件并编写内容
- $ sudo VIM Dockerfile
- # Nginx
- # VERSION 1.0
- FROM Ubuntu
- MAINTAINER gongziqi 1415583094@qq.com
- RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
- # 2. 查看当前本地镜像
- $ sudo docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- # 3. build Dockerfile 文件, 创建镜像
- $ sudo docker build -t nginx/mynginx /opt/tmp_dockerbuilder/Dockerfile
- Sending build context to Docker daemon 2.048kB
- Step 1/3 : FROM Ubuntu
- ---> 4e5021d210f6
- Step 2/3 : MAINTAINER gongziqi 1415583094@qq.com
- ---> Running in 8dc5269da475
- Removing intermediate container 8dc5269da475
- ---> e27af3f3a447
- Step 3/3 : RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
- ---> Running in 2ec0f5b9fc81
- ........
- ........
- ........
- Successfully built d27de6c7896d
- Successfully tagged nginx/mynginx:latest
- # 4. 再次查看本地镜像
- $ sudo docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- nginx/mynginx latest d27de6c7896d 6 minutes ago 275MB
- # 5. 以当前创建的镜像运行容器
- $ sudo docker run -ti d27de6c7896d /bin/bash
- root@a505965d1b84:/#
- # 6. 查看当前的容器中是否有我们刚才需要安装的相关软件
- root@a505965d1b84:/# find / -name apache2
- /etc/cron.daily/apache2
- /etc/init.d/apache2
- /etc/logrotate.d/apache2
- /etc/apache2
- /etc/ufw/applications.d/apache2
- find: '/proc/1/map_files': Operation not permitted
- find: '/proc/12/map_files': Operation not permitted
- /usr/lib/apache2
- /usr/sbin/apache2
- /usr/share/bug/apache2
- /usr/share/doc/apache2
- /usr/share/lintian/overrides/apache2
- /usr/share/apache2
- /var/cache/apache2
- /var/lib/apache2
- /var/log/apache2
- # 7. 查看 Ubuntu 镜像运行的容器中是否有 apache2
- $ sudo docker run -tid Ubuntu /bin/bash
- $ sudo docker exec -ti 6df8ff14f57f /bin/bash
- root@6df8ff14f57f:/# find / -name apache2
- find: '/proc/1/map_files': Operation not permitted
- find: '/proc/10/map_files': Operation not permitted
- find: '/proc/19/map_files': Operation not permitted
- root@6df8ff14f57f:/#
- # 说明: 我们会发现刚才的配置的 apache2 软件已被安装, 而基于的 Ubuntu 镜像本身是没有 apache2 的
来源: https://www.cnblogs.com/chuanqi1415583094/p/12685136.html