Dockerfile的基本操作
- Dockerfile简单介绍
- Dockerfile的主要组成部分
- Dockerfile的基本指令
- 快速入门Dockerfile
- Dockerfile指令的用法
- Copy(官方更推荐)
- ADD
- CMD
- ENTRYPOINT
- ARG和ENV指令
- VOLUME
- EXPOSE
- WORKDIR
- USER
定制docker镜像的两种方式
- 手动修改容器内容,导出并保存新的镜像
- 基于Dockerfile自行编写指令,基于指令流程创建镜像
镜像是多层存储,每一层在前一层的基础上进行修改
容器也是多层存储,以镜像为基础层,在其基础上加一层作为容器运行时的存储层
Dockerfile简单介绍
- 通过在dockerfile中定义一系列的命令和参数构成的脚本,然后将这些命令应用于基础镜像,依次添加添加层,最终生成一个新的镜像
CentOS官方提供的dockerfile实例
以 Nginx的dockerfile 为例
# "ported" by Adam Miller <maxamillion@fedoraproject.org> from
# https://github.com/fedora-cloud/Fedora-Dockerfiles
#
# Originally written for Fedora-Dockerfiles by
# scollier <scollier@redhat.com>
#
# Enriched by patterns found at https://github.com/openshift/postgresql/blob/master/9.4/Dockerfile.rhel7 by
# Christoph Görn <goern@redhat.com>
FROM centos:centos7
MAINTAINER The CentOS Project <cloud-ops@centos.org>
# Labels consumed by Red Hat build service
LABEL Component="nginx" \
Name="centos/nginx-180-centos7" \
Version="1.8.0" \
Release="1"
# Labels could be consumed by OpenShift
LABEL io.k8s.description="nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev." \
io.k8s.display-name="nginx 1.8.0" \
io.openshift.expose-services="80:http" \
io.openshift.tags="nginx"
RUN yum -y install --setopt=tsflags=nodocs centos-release-scl-rh && \
yum -y update --setopt=tsflags=nodocs && \
yum -y install --setopt=tsflags=nodocs scl-utils rh-nginx18 && \
yum clean all && \
mkdir -p /usr/share/nginx/html
# Get prefix path and path to scripts rather than hard-code them in scripts
ENV CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/nginx \
ENABLED_COLLECTIONS=rh-nginx18
# When bash is started non-interactively, to run a shell script, for example it
# looks for this variable and source the content of this file. This will enable
# the SCL for all scripts without need to do 'scl enable'.
ENV BASH_ENV=${CONTAINER_SCRIPTS_PATH}/scl_enable \
ENV=${CONTAINER_SCRIPTS_PATH}/scl_enable \
PROMPT_COMMAND=". ${CONTAINER_SCRIPTS_PATH}/scl_enable"
ADD root /
# ADD https://git.centos.org/sources/httpd/c7/acf5cccf4afaecf3afeb18c50ae59fd5c6504910 /usr/share/nginx/html/
# RUN sed -i -e 's/Apache/nginx/g' -e '/apache_pb.gif/d' /usr/share/nginx/html/index.html
RUN echo "nginx on CentOS7" > /usr/share/nginx/html/index.html
EXPOSE 80
USER nginx
ENTRYPOINT ["container-entrypoint"]
CMD [ "nginx18" ]
Dockerfile的主要组成部分
- 基础镜像信息 FROM
- 制作镜像的操作指令 RUN、ADD等
- 容器启动时执行指令 CMD
docker run 镜像名
Dockerfile的基本指令
- FROM 指定基础镜像
- MAINTAINER 指定维护者信息,可以缺失
- RUN 运行命令行指令
- ADD 复制文件,会自动进行解压
- WORKDIR 设置当前工作目录
- VOLUME 设置卷,挂载主机目录(
docker run -v 参数
) - EXPOSE 指定对外的端口号(
docker run -p 参数
) - CMD 指定容器启动后要执行的任务
- COPY 仅复制文件
- ENV 定义环境变量
- ENTERPOINT 容器启动后执行的任务
快速入门Dockerfile
示例:dockerfile构建nginx镜像,并修改nginx的index.html文件
[root@centos /]$ cd /home/eishin/
[root@centos eishin]$ mkdir ./LearnDockerfile
[root@centos eishin]$ cd LearnDockerfile/
[root@centos LearnDockerfile]$ touch Dockerfile
[root@centos LearnDockerfile]$ vim Dockerfile
# 构建dockerfile
[root@centos LearnDockerfile]$ docker build .
[+] Building 0.1s (4/5)
[+] Building 0.3s (4/5)
[+] Building 0.3s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 150B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/nginx:latest 0.0s
=> [1/2] FROM docker.io/library/nginx 0.1s
=> [2/2] RUN echo '<meta charset=utf8>通过dockerfile创建的nginx服务' > /usr/share/nginx/html/index.html 0.2s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:6e4b25c52bc0efcd92d6def8a3a9c73c3989862df4f4944c771aa831ef40959b
[root@centos LearnDockerfile]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 6e4b25c52bc0 About a minute ago 142MB
centos_vim latest 66a5241671c2 3 weeks ago 457MB
redis latest ec466c2297ad 3 weeks ago 117MB
nginx latest 9eee96112def 3 weeks ago 142MB
ubuntu latest 58db3edaf2be 5 weeks ago 77.8MB
centos 7.8.2003 afb6fca791e0 2 years ago 203MB
# 取名
[root@centos LearnDockerfile]$ docker tag 6e4b25c52bc0 my_nginx
# 运行镜像
[root@centos LearnDockerfile]$ docker run -d -p 80:80 my_nginx
# 宿主机浏览器访问80端口
dockerfile内容
FROM nginx
RUN echo '<meta charset=utf8>通过dockerfile创建的nginx服务' > /usr/share/nginx/html/index.html
Dockerfile指令的用法
Tips: 采用dockerfile创建镜像时所有操作都应该是非交互式的,对配置文件的修改应该采用 sed 命令
Copy(官方更推荐)
COPY指令从宿主机复制文件(或目录)到新的一层镜像内
例如
COPY project.py /home/
# 支持多个文件,以及通配符形式复制,语法满足Golang的filepath.match
COPY project* /tmp/cc?.txt /home/
COPY指令能够保留源文件的元数据,例如权限、访问时间等等
ADD
特性和COPY基本一致,增加了如下的功能
1. 源文件是一个url时,会下载该链接,放入目标路径,且权限为600
2. 源文件是一个url,且是一个压缩包时,不会自动解压
3. 源文件是一个压缩文件,且是gzip, bzip2, xz, tar时,会自动解压该文件
到目标目录下
CMD
CMD ["参数1", "参数2", ...]
运行shell命令,会被转化为shell形式
例如 CMD echo $PATH
会转化为 CMD ["sh", "-c", "echo $PATH"]
ENTRYPOINT
在指定了ENTRYPOINT后,命令行指令的语义发生了变化,将命令行指令的内容当作参数传递给ENTRYPOINT指令
准备一个dockerfile文件
FROM centos:7.8.2003
RUN rpm --rebuilddb && yum install epel-release -y
RUN rpm --rebuilddb && yum install curl -y
CMD ["curl", "-s", "http://ipinfo.io/ip"]
命令行操作
[root@centos LearnDockerfile]$ echo > Dockerfile
[root@centos LearnDockerfile]$ vim Dockerfile
[root@centos LearnDockerfile]$ docker build .
[+] Building 355.1s (7/7) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 196B 0.0s
=> [internal] load metadata for docker.io/library/centos:7.8.2003 0.0s
=> CACHED [1/3] FROM docker.io/library/centos:7.8.2003 0.0s
=> [2/3] RUN rpm --rebuilddb && yum install epel-release -y 344.3s
=> [3/3] RUN rpm --rebuilddb && yum install curl -y 10.1s
=> exporting to image 0.6s
=> => exporting layers 0.6s
=> => writing image sha256:fa211f6f8a29777b7484ec6f0accf7eeb6eacf03dc19b28a5da2873a64d0b6d1
[root@centos LearnDockerfile]$ docker tag fa211f6f8a29 my_centos
[root@centos LearnDockerfile]$ docker run my_centos
183.173.90.208
# 不支持额外参数
[root@centos LearnDockerfile]$ docker run my_centos -I
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-I": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
不支持额外参数的解决办法
- 传入完整的命令
docker run my_centos curl -s http://ipinfo.io/ip -I
- 使用ENTRYPOINT指令,修改dockerfile如下
FROM centos:7.8.2003
RUN rpm --rebuilddb && yum install epel-release -y
RUN rpm --rebuilddb && yum install curl -y
ENTRYPOINT ["curl", "-s", "http://ipinfo.io/ip"]
ARG和ENV指令
设置环境变量
维护dockerfile脚本更方便
ENV <Key1>="<value1>" <Key2>="<value2>" ...
例如
ENV MYSQL_VERSION=5.6
RUN yum install mysql-${MYSQL_VERSION}
ENV设置的环境变量在容器构建时和容器运行时都可以使用
ARG也是设置环境变量,但是只能用于容器构建
VOLUME
Tips: 容器在运行时,应该保证在存储层不写入任何数据。运行时在容器内产生的数据,推荐挂载并写入到宿主机上进行维护。
VOLUME /data
# 容器内的/data文件夹在容器运行时,该目录自动挂载为匿名卷,
# 任何向该目录中写入数据的操作都不会被容器记录
也支持写入列表
VOLUME ["/data1", "/data2"]
EXPOSE
用于指定容器运行时对外提供的端口服务
docker port 容器 # 查看容器的端口信息
docker run -p 宿主机端口:容器内端口
docker run -P # 表示 随机宿主机端口:容器内端口
WORKDIR
用于在dockerfile脚本中更改工作目录,类似Linux命令行窗口下的cd命令
USER
用于改变环境,用于切换用户