[Docker学习笔记]利用Dockerfile创建镜像

Dockerfile 指令

指令 作用
from 继承基础镜像
maintainer 镜像制作者信息(可缺省)
run 用来执行shell命令
expose 暴露端口号
cmd 启动容器默认执行的命令
entrypoint 启动容器真正执行的命令
volume 创建挂载点
env 配置环境变量
add 复制文件到容器
copy 复制文件到容器
workdir 设置容器的工作目录
user 使用容器的用户

from:指定基础镜像

必须为第一个命令

  • 格式

    dockerfile 复制代码
    from <image[:tag]> #tag可以缺省,拉取最新版
    from <image>@<digest> #摘要唯一地标识了镜像的特定版本,不会改变,即使镜像的内容发生变化
    # 同样digest摘要也可以省略
  • 示例

    dockerfile 复制代码
    FROM mysql:5.6

run:构建镜像时执行的命令

RUN是Dockerfile中的一个重要指令,用于在镜像中执行命令,以便在构建过程中安装软件包、配置环境、生成文件等。RUN指令执行的命令会在新的镜像层中运行,并且在后续构建中,只有在该层之前的内容发生变化时才会重新运行,利用了Docker的缓存机制,提高了构建速度。

run指令执行方式
shell 格式(默认格式)
dockerfile 复制代码
RUN apt-get update && apt-get install -y python3
exec 格式

数组格式,可以避免在Shell中发生意外的解释问题

dockerfile 复制代码
RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y", ""]

cmd:定义容器启动时默认要执行的命令

一个Dockerfile中只能包含一个CMD指令,如果有多个,则只有最后一个CMD指令会生效

cmd指令执行方式
shell 格式
dockerfile 复制代码
CMD python app.py
exec格式
dockerfile 复制代码
CMD ["python", "app.py"]
【补充】如果在docker run命令中指定了其他命令,则会覆盖CMD指令中的默认命令。

例如,如果在启动容器时执行以下命令,就会覆盖CMD中定义的默认启动命令

bash 复制代码
docker run my_image python script.py
# 容器启动时会执行script.py脚本

entrypoint:配置容器启动时的默认执行命令

  1. ENTRYPOINT指令的命令会在容器启动时始终执行,无论在docker run命令中是否指定了其他命令。它不会被覆盖,而是作为容器的主要执行命令。
  2. 如果在docker run命令中指定了其他命令,这些命令将作为ENTRYPOINT指令的参数进行传递。也就是说,ENTRYPOINT指令中的命令将成为执行时的前缀
entrypoint例子
复制代码
FROM centos:7
 
ENTRYPOINT ["echo", "Hello"]
如果我们构建该镜像并运行容器,不提供其他参数,那么容器启动后将输出 "Hello"
bash 复制代码
$ docker build -t my_image .
$ docker run my_image
Hello
如果我们在运行容器时提供了其他参数,那么这些参数将作为ENTRYPOINT指令中命令的参数
bash 复制代码
$ docker run my_image ls
Hello ls
# 此时的ls已经不是命令了,而是作为一个参数传递给entrypoint
# 类似于ENTRYPOINT ["echo", "Hello","ls"]

在实际应用中,可以使用ENTRYPOINT指令来定义一个可执行的程序或脚本,然后在容器启动时运行这个程序,并将Docker容器作为可执行应用来使用。这样可以确保容器在运行时的行为是可预期的,而且可以将容器配置和执行逻辑完全封装在镜像内部,使得容器的使用更加方便和易于管理。

这段话说简单点:无论用户以什么样的方式执行docker run,最后都会执行entrypoint指定的动作(前提是有entrypoint)

expose:用于暴露网络端口

它并不会实际上打开或映射端口,而是作为一个文档功能,用于告知用户该镜像内的服务或应用程序将使用指定的端口

dockerfile 复制代码
FROM centos:7
 
# 声明容器将监听80端口
EXPOSE 80

在使用docker run命令启动容器时,如果需要通过主机访问容器的80端口,还需要使用-p选项来进行端口映射

bash 复制代码
$ docker built -t my_image . #先docker build创建镜像
$ docker run -p 8080:80 my_image # 映射宿主机8080端口提供容器服务

env:设置环境变量

格式

dockerfile 复制代码
ENV [key]=[value]
# key是环境变量的名称,value是环境变量的值
# 在镜像构建过程中,这些环境变量会被设置为指定的值
dockerfile 复制代码
FROM centos:7
 
# 设置环境变量
ENV MY_NAME yy
ENV APP_HOME /app
 
# 创建目录并设置工作目录
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
 
# 复制应用程序到镜像中
COPY . .
 
# 在运行时输出环境变量
CMD echo "Hello, i am $MY_NAME"
bash 复制代码
 docker build -t dockerfile:test .
bash 复制代码
docker images
bash 复制代码
docker run --name env_test1 dockerfile:test
【补】在运行容器时,你可以通过docker run -e选项来覆盖环境变量的值
bash 复制代码
docker run --name env_test2 -e MY_NAME="Alice" dockerfile:test

add:将文件、目录或远程URL复制到镜像中

格式

dockerfile 复制代码
add [源文件][目的地址]

除了复制文件和目录,ADD指令还支持自动解压缩。如果源文件是一个压缩文件(例如.tar、.tar.gz、.tgz、.zip等),那么ADD指令会自动解压缩该文件到指定的目录

例子

复制本地文件到镜像中

dockerfile 复制代码
ADD app.py /app/

复制本地目录到镜像中

dockerfile 复制代码
ADD src/ /app/

从远程URL下载文件并复制到镜像中

dockerfile 复制代码
ADD https://example.com/file.tar.gz /tmp/

解压缩压缩文件并复制到镜像中

dockerfile 复制代码
ADD app.tar.gz /app/

copy:将本地文件或目录复制到镜像

不支持自动解压缩

复制本地文件到镜像中:

dockerfile 复制代码
COPY app.py /app/

复制本地目录到镜像中

dockerfile 复制代码
COPY src/ /app/

【补】copy 和 add 的区别

在构建镜像时,Docker将会在镜像的文件系统层中添加复制的文件或目录。这使得镜像的构建过程更加明确,不会产生自动解压缩的不确定行为。相对于ADD指令,COPY指令更为推荐,特别是在只需要简单复制本地文件或目录的情况下。COPY指令功能简单,不容易引起不必要的意外行为。对于大多数复制文件的场景,建议使用COPY指令

volume:用于声明挂载点

挂载点(数据卷)是一个特殊的目录,它可以绕过联合文件系统(UnionFS),并在容器间共享数据

在一个Dockerfile中可以使用多个VOLUME指令来声明多个挂载点

dockerfile 复制代码
FROM centos:7
 
# 声明两个挂载点/app/data和/app/logs,这样在运行容器时,可以将这两个挂载点映射到主机的文件系统中,以实现数据持久化和共享
VOLUME ["/app/data", "/app/logs"]

运行容器时,可以使用-v选项或--mount选项来将主机的目录或数据卷映射到容器的挂载点

bash 复制代码
docker run -v /host/data:/app/data -v /host/logs:/app/logs my_image
# 将主机的/host/data和/host/logs目录分别映射到容器中的/app/data和/app/logs挂载点,实现了主机和容器之间的数据共享

workdir:用于设置工作目录

在容器启动时,进程的当前工作目录将被设置为WORKDIR指令所指定的目录

dockerfile 复制代码
FROM centos:7
 
# 设置工作目录
WORKDIR /app
 
# 容器启动时运行的命令
CMD ["python", "app.py"]

# 当容器启动时,进程的当前工作目录将自动设置为/app,这样在执行CMD指令时,不需要使用绝对路径来运行python app.py

user:用于指定在容器中运行镜像时要使用的非特权用户

默认情况下,Docker容器在启动时以root用户身份运行,这意味着容器内的进程具有最高权限。然而,为了加强安全性,避免潜在的安全风险,最好以非特权用户的身份运行容器中的应用程序

dockerfile 复制代码
FROM centos:7
 
# 创建一个新用户并切换到该用户
RUN useradd -ms /bin/bash myuser
USER myuser
 
# 设置工作目录
WORKDIR /app
 
# 复制应用程序到工作目录
COPY . .
 
# 设置环境变量
ENV APP_ENV production
 
# 容器启动时运行的命令
CMD ["python", "app.py"]

#使用useradd命令创建了一个名为myuser的新用户,并使用-ms /bin/bash选项指定了创建用户时使用的shell。
#通过USER指令切换到了myuser用户
#在容器运行时,进程将以myuser用户的身份运行,而不是以root用户身份

用dockerfile制作镜像

命令

bash 复制代码
docker build -t <容器名[:标签名]> <dockerfile所在目录>
bash 复制代码
docker build -t dockerfile:test_new .
bash 复制代码
docker images

接下来就可以用docker run 命令来启动容器

相关推荐
黑客思维者2 分钟前
机器学习014:监督学习【分类算法】(逻辑回归)-- 一个“是与非”的智慧分类器
人工智能·学习·机器学习·分类·回归·逻辑回归·监督学习
程序员大辉16 分钟前
比notion更好用的markdown笔记工具Obsidian
笔记
l1t23 分钟前
利用docker在windows 11 wsl中安装oracle 12cR2
运维·windows·docker·oracle·容器
race condition28 分钟前
UNIX网络编程笔记 信号处理
笔记·unix·信号处理
旖旎夜光29 分钟前
Linux知识(1)(下)
linux·学习
秋深枫叶红42 分钟前
嵌入式第三十九篇——linux系统编程——信号通信、共享内存
linux·运维·服务器·学习
arron889942 分钟前
以目标检测基础知识学习分割模型算法
学习·算法·目标检测
JAVA+C语言1 小时前
Python新手学习
开发语言·python·学习
龚子亦1 小时前
【GameFramework框架】FSM使用
学习·unity·游戏开发·游戏框架
roman_日积跬步-终至千里1 小时前
【人工智能导论】07-学习-CNN:卷积+池化+多层堆叠,有效处理图像等结构化数据
人工智能·学习·cnn