1.Dockerfile 指令介绍
-
FROM 这个镜像的妈妈是谁?(指定基础镜像)
-
MAINTAINER 告诉别人,谁复制养它(指定维护者信息,可以没有)
-
RUN 你想让它干啥(在命令前面加上 RUN 即可)
-
ADD 添加宿主机的文件到容器里,还多了一个自动解压的功能
-
COPY 作用和ADD是一样的,都是拷贝宿主机的文件到容器内,COPY 就是仅仅拷贝
-
WORKDIR 我是cd,今天刚化了妆(设置当前工作目录)
-
VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
-
EXPOSE 它要打开的门是啥(指定对外的端口)
-
CMD 奔跑吧,兄弟!(指定容器启动后要干的事情)
-
ENV 环境变量
-
ENTRYPOINT 容器启动后执行的命令
2.使用 Dockerfile 构建镜像
-
写一个 dockerfile 构建一个 nginx 镜像,运行生成容器后,并且对 nginx 的首页内容进行更改
# 创建 Dockerfile,注意文件名,必须是 Dockerfile,内容如下
FROM nginx
RUN echo '<meta charset=utf8> tfos 带你用 docker 运行 nginx 服务.' > /usr/share/nginx/html/index.html
# 在 Dockerfile 文件目录下构建镜像,. 表示当前目录
docker build .
# 查看镜像
docker images
# 修改镜像名
docker tag 镜像id 修改后的镜像名
# 运行该镜像,生成容器
docker run -d -p 80:80 镜像名称
# 查看当前运行的容器
docker ps
-
访问宿主机的 80 端口
3.COPY 指令
-
copy 指令从宿主机复制文件/目录到新的一层镜像内,copy 指令能够保留源文件的元数据,如权限,访问时间等等,这点很重要
# 复制宿主机文件到镜像内指定的目录
copy 宿主机文件 镜像目录
# 支持多个文件,以及通配符形式复制,语法要满足 Golang 的 filepath.Match
copy 文件名* /tmp/tfos?.tex. /home
4.ADD 指令
-
特性和 COPY 基本一致,不过多了些功能
-
源文件是一个 URL,此时 docker 引擎会下载该链接,放入目标路径,且权限自动设为 600,若这不是期望结果,还得增加一层 RUN 指令进行调整
-
源文件是一个 URL,且是一个压缩包,不会自动解压,也得单独用 RUN 指令解压
-
源文件是一个压缩文件,且是 gzip,bzip2,xz,tar 情况,ADD 指令会自动解压缩该文件到目标路径
-
-
Dockerfile 官方更为推荐使用 COPY,ADD 包含了更多复杂的功能,且 ADD 会使构建缓存失效,导致镜像构建缓慢
5.CMD 指令
-
用法,注意是双引号,在指定了 entrypoint 指令后,用 CMD 指定具体的参数
CMD ["参数1","参数2"]
-
docker 不是虚拟机,容器就是一个进程,既然是进程,那么程序在启动的时候需要指定些运行参数,这就是 CMD 指令
-
例如 centos 镜像默认的 CMD 是 /bin/bash,直接 docker run -it centos 会直接进入 bash 解析器,等同于:CMD ["/bin/bash"]
-
也可以启动容器时候,指定参数,docker run -it centos cat /etc/os-release,等同于:CMD ["cat","/etc/os-release"]
-
-
CMD 指令 shell 命令,也会被转化为 shell 形式,例如 CMD echo $PATH 会被转换为 CMD ["sh","-c","echo $PATH"]
6.容器内运行程序
-
这里要注意的是,docker 不是虚拟机的概念,虚拟机里的程序运行,基本上都是在后台运行,利用 systemctl 运行,但是容器内没有后台进程的概念,必须在前台运行
-
容器就是为了主进程而存在的,主进程如果退出了,容器也就丢失意义,自动退出
-
例如有一个经典问题
-
CMD systemctl start nginx,这样的写法是错误的,容器会立即退出
-
因为 systemctl start nginx 是希望以守护进程形式启动 nginx,且 CMD 命令会转换为:CMD ["sh","-c","systemctl start nginx"]
-
这样的命令主进程是 sh 解析器,执行完毕后立即结束了,因此容器也就退出了
-
因此正确的做法应该是 CMD ["nginx","-g","daemon off;"]
-
7.ENTRYPOINT 指令
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"]
-
和 RUN 指令一样,分为两种格式:exec 和 shell
-
作用和 CMD 一样,都是在指定容器启动程序以及参数
-
当指定了 ENTRYPOINT 之后,CMD 指令的语义就有了变化,而是把 CMD 的内容当作参数传递给 ENTRYPOINT 指令
-
实际用法
-
准备好 Dockerfile
-
-
构建镜像
docker build .
-
查看镜像
docker images
-
修改镜像名称
docker tag 镜像id 修改后的镜像名称
-
根据名字查找镜像
docker images | grep 修改后的镜像名称
-
运行镜像,生成容器实例,没有前台运行,因此立即挂了
docker run 修改后的镜像名称
-
上述运行正确,但是我想再传入一个参数,该怎么操作?发现是无法直接传入参数的,该形式是覆盖镜像中的 CMD,就好比把该 docker 镜像当作一个环境去执行后的命令
-
想要争取的给容器传入一个 -I 参数,该怎样操作?
-
解决办法1,导致镜像没有意义
docker run 修改后的镜像名称 curl -s http://ipinfo.io/ip -I
-
解决办法2,使用 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"]
# 重新构建镜像
docker build .
# -t 指定构建镜像 tag 名称
docker build -t '镜像名称' .
# --no-cache 构建时不使用旧的缓存,重新下载生成新的缓存
docker build --no-cache -t '镜像名称' .
# 查看本机所有镜像
docker images
# 重新修改镜像名称
docker tag 镜像id 新的镜像名称
# 根据镜像名称查找镜像
docker images | grep 修改后的镜像名称
# 重新运行镜像,生成容器,传入的 CMD 参数作为 ENTRYPOINT 的参数来执行
docker run 新的镜像名称 -I
8.ARG 和 ENV 命令
-
ENV 设置环境变量,后续所有的操作,通过 $变量名 就可以直接获取变量值绑定了,维护 dockerfile 脚本时更友好方便
-
ARG 和 EVN 一样,都是设置环境变量,区别在于 EVN 无论是在镜像构建,还是容器运行,该变量都可以使用;ARG 只是用于构建镜像需要设置的变量,容器运行时就消失了
ENV NAME="tfos"
ENV AGE="18"
ENV MYSQL_VERSION=8.0
9.VOLUME 指令
-
容器在运行时,应该保证在存储层不写入任何数据,运行在容器内生产的数据,我们推荐是挂载,写入到宿主机上,进行维护
# 将容器内的 /data 文件夹,在容器运行时,该目录自动挂载为匿名卷,任何向该目录中写入数据的操作,都不会被容器记录,保证的容器存储层无状态理念
VOLUME /data # Dockerfile 样例
FROM centos:7.8.2003
MAINTAINER tfos
VOLUME ["/data1","data2"]
# 该容器运行时,这两个目录自动和宿主机目录做好映射关系
docker build .
docker run 镜像id
docker inspect 镜像id
-
容器数据挂载的方式,通过 dockerfile,指定 VOLUME 目录
-
通过 docker run -v 参数,直接设置需要映射挂载的目录
10.EXPOSE 指令
-
指定容器运行时对外提供的端口服务
-
帮助使用该镜像的人,快速理解该容器的一个端口业务
docker port 容器
docker run -p 宿主机端口:容器端口
# -P 随机宿主机端口:容器端口
docker run -P
11.WORKDIR 指令
-
用于在 dockerfile 中,目录的切换,更改工作目录
WORKDIR /opt
12.USER 指令
-
用于改变环境,用于切换用户
USER root