赞
踩
Dockerfile 是镜像的描述文件,Docker 可以读取这个文件生成新的镜像。
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:
Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
构建三步骤:
Docker hub 上的镜像也给出了 Dockerfile 文件链接,可以点击查看参照。
Dockerfile 基础信息:
基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是 FORM
镜像维护者的姓名和邮箱地址
构建镜像时(Docker build)运行的命令
两种格式
RUN 命令
RUN yum install -y node
yum install -y node
RUN ["可执行文件", "参数1", "参数2"]
RUN ["./test.php", "dev", "offline"
等同于RUN ./test.php dev offline
当前容器对外暴露出的端口
指定在创建容器后,终端默认登录的进来工作目录,一个落脚点。比如 Tomcat 镜像,一进入容器终端,当前目录为/usr/local/tomcat
指定该镜像以什么样的用户去执行,如果都不指定,默认是root。
USER 用户名:用户组 或
USER 用户id:组id
用来在构建镜像过程中设置环境变量。
举个例子:
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面定义了别名一样;也可以在其它指令中直接使用这些环境变量。
比如,设置默认工作目录:WORKDIR $MY_PATH
ADD <src> <dest>
COPY 类似 ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
和 RUN 一样两种格式:
COPY src dest
COPY ["src", "dest"]
<src源路径>:源文件或者源目录
<dest目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
注意
# 使用相对路径的栗子
ADD test.txt relativeDir/
# 等价于
ADD test.txt <WORKDIR>/relativeDir/
# 使用绝对路径的栗子
# 将 test.txt 添加到 /absoluteDir/ 目录下
ADD test.txt /absoluteDir/
# test.txt 是相对路径,相对于构建上下文
COPY test.txt /mkdir/
# 错误写法,文件均不在上下文目录中,并不会被找到
# 这个找的就是构建上下文的上级目录的 test.txt
COPY ../test.txt /mkdir/
# 这个找的是本机根目录下的 test.txt
COPY /test.txt /mkdir/
根据官方 Dockerfile 最佳实践,除非真的需要从远程 url 添加文件或自动提取压缩文件才用 ADD,其他情况一律使用 COPY。
总结:
容器数据卷,用于数据保存和持久化工作
两者都是指定新建的镜像运行时(docker run),容器终端中默认执行的命令。
比如运行 ubuntu 镜像:docker run -it ubuntu
,一运行就直接启动了 Ubuntu 系统的 bash。应该就是构建 ubuntu 镜像时,Dockerfile 通过 CMD 或者 ENTRYPOINT 指定了默认启动 bash。
两者指定的命令,最好是阻塞式命令,也就是有前台任务的命令,比如 bash,tail 这些。要不然如果是非阻塞式的命令,命令一运行完毕,容器就退出停止执行了。
Dockerfile 中这两个指令必须要有一个,如果没有则从父镜像中继承,如果父镜像也没有,则镜像构建失败。
两者和 RUN 一样有两种格式定义命令,shell 和 exec。
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。
比如 Redis,直接运行docker run -it redis
它直接进入 Redis 控制命令行。如果运行docker run -it redis /bin/bash
,就会进入 Redis 容器的虚拟 Linux 环境终端,需要再运行redis-cli
才能进入 Redis 命令控制行。
[root@192 app]# docker run -it redis
1:C 08 Feb 2023 19:57:36.965 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
......
1:M 08 Feb 2023 19:57:36.968 * Ready to accept connections
(ctrl + c)
1:M 08 Feb 2023 19:58:37.474 # Redis is now ready to exit, bye bye...
[root@192 app]# docker run -it redis /bin/bash
root@b5df641baaa0:/data# redis-cli
FROM alpine
WORKDIR /docker
RUN echo 111 >> 1.txt
RUN echo 222 >> 2.txt
RUN echo 333 >> 3.txt
CMD ["cat","/docker/2.txt"]
ENTRYPOINT ["cat","/docker/1.txt"]
docker build -t test1 .
docker run test1 #执行的命令相当于 cat 1.txt cat 2.txt
> cat: can't open 'cat': No such file or directory
> 111
> 222
docker run test1 3.txt #执行的命令相当于 cat 1.txt 3.txt
> 111
> 333 #docker run 后面参数代替了 CMD
[ENTRYPOINT命令] /bin/sh -c [CMD命令]
,因为整个命令中间多了一个/bin/sh -c
命令通常会导致整个命令无效。所以这种混合格式使用要少用。
sh -c
命令,它可以让 bash 将一个字串作为完整的命令来执行。FROM alpine
WORKDIR /docker
RUN echo 111 >> 1.txt
RUN echo 222 >> 2.txt
RUN echo 333 >> 3.txt
CMD cat /docker/2.txt
ENTRYPOINT ["cat","/docker/1.txt"]
docker build -t test1 . docker run test2 #执行的命令相当于 cat 1.txt /bin/sh -c cat 2.txt #因为 cat 命令无法识别 -c 选项,所以导致整个命令无效报错 cat: unrecognized option: c BusyBox v1.34.1 (2021-11-23 00:57:35 UTC) multi-call binary. Usage: cat [-nbvteA] [FILE]... Print FILEs to stdout -n Number output lines -b Number nonempty lines -v Show nonprinting characters as ^x or M-x -t ...and tabs as ^I -e ...and end lines with $ -A Same as -vte docker run test2 3.txt #覆盖了CMD,所以命令正常 > 111 > 333
官网介绍的区别:
Both and instructions define what command gets executed when running a container. There are few rules that describe their co-operation.CMD ENTRYPOINT
CMD ENTRYPOINT
ENTRYPOINT
should be defined when using the container as an executable.CMD
should be used as a way of defining default arguments for an command or for executing an ad-hoc command in a container.ENTRYPOINT
CMD
will be overridden when running the container with alternative arguments.The table below shows what command is executed for different / combinations:ENTRYPOINTCMD
Note:
If is defined from the base image, setting will reset to an empty value. In this scenario, must be defined in the current image to have a value.CMD ENTRYPOINT CMD CMD
不同阶段,发挥作用的关键字。
BUILD | BOTH | RUN |
---|---|---|
FORM | WORKDIR | CMD |
MAINTAINER | USER | ENV |
COPY | EXPOSE | |
ADD | VOLUME | |
RUN | ENTRYPOINT | |
ONBUILD | ||
.dockerignore |
需求:构建带有 vim+ifconfig+jdk17 的 centos 镜像。
下载 jdk17 到 Dockerfile 文件所在目录(这里为:/docker)
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz -P /docker/
编写 Dockerfile:
FROM centos7 MAINTAINER ikun ENV MYPATH /usr/local WORKDIR $MYPATH #安装vim编辑器 RUN yum -y install vim #安装ifconfig命令查看网络IP RUN yum -y install net-tools #安装lib库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java #ADD 是相对路径jar,把jdk添加到容器中,安装包必须要和Dockerfile文件在同一位置 ADD jdk-17_linux-x64_bin.tar.gz /usr/local/java/ #配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk-17.0.6 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH ENV PATH $JAVA_HOME/bin:$PATH EXPOSE 80 #CMD的覆盖不影响CMD输出 CMD echo $MYPATH CMD echo "success--------------ok" CMD /bin/bash
语法:docker build -t <镜像名>:<tag> <Dockerfile文件目录>
举例:docker build -t myCentos .
虚悬镜像就是镜像名和 tag 都是 none 的镜像。
我们在构建的时候,不小心忘记填写镜像名和 tag,如docker build .
就会构建出虚悬镜像。
查看本机的虚悬镜像列表:docker image ls -f dangling=true
虚悬镜像没有价值,建议删除:docker image prune
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。