Bootstrap

Docker_一刀流_好用、好玩还方便_(持续更新)

简介

Docker 是一个开源的容器化平台,它允许开发者打包应用及其所有依赖项到一个标准化的单元中,这个单元被称为容器。容器化是一种轻量级的、可移植的、自给自足的软件运行环境。

Docker 的核心概念

  • 容器(Container): 一个轻量级的执行环境,包含了运行某个应用所需的代码、运行时、系统工具、库和设置。容器在运行时与其他容器相互隔离,并且共享同一操作系统内核。
  • 镜像(Image): 容器的蓝本,包含有创建容器所需的全部内容。当你启动一个容器时,Docker会基于镜像来创建它。
  • 仓库(Registry): 是Docker存储镜像的地方。最流行的公共仓库是Docker Hub,它包含了大量的预先构建好的镜像,可以直接下载使用。

容器和镜像具体是做什么的、有什么联系,后面会说。
Docker 的作用

  • 简化配置: 开发者可以通过Docker快速构建一个复杂的软件堆栈,并确保这个堆栈在不同环境下始终如一地运行。
  • 代码流水线管理: Docker可以帮助开发者将代码自动化构建并测试,实现持续集成和部署
  • 应用隔离: Docker保证了应用与应用之间的隔离,提高了安全性。
  • 透明度: Docker镜像包含代码、运行时、系统工具、系统库和设置,减少了“在我这里运行正常”的问题。
  • 微服务架构: Docker非常适合微服务架构,因为它支持每个服务都可以独立容器化。
  • 资源利用率和效率: 与虚拟机相比,容器需要更少的系统资源,因为它们共享主机的内核,而不是模拟整个操作系统。

Docker 与虚拟机的比较
Docker容器通常被看作是虚拟机(Virtual Machine, VM)的一个轻量级替代品。两者最大的区别在于:

  • 虚拟机: 在硬件级别模拟出多个执行环境,每个环境都有完整的操作系统和虚拟硬件,消耗资源较多。
  • 容器: 不需要完整的操作系统实例,它们更加轻量,启动更快,占用资源更少。

一、镜像和容器的概念

在 Docker 中,镜像和容器是两个核心概念,它们之间有着密切的关系。理解它们的关系有助于更好地使用 Docker。

镜像(Image)

  • 定义:镜像是一个轻量级的、独立的、可执行的软件包,包含运行某个应用程序所需的代码、运行时、库、环境变量和配置文件。镜像是一个只读模板,用于创建 Docker 容器。
  • 用途:镜像是容器的基础。你可以把镜像看作是容器的蓝图或快照,提供了创建容器的所有必要信息。
  • 存储:镜像存储在 Docker 注册表中(如 Docker Hub),可以从这些注册表中下载并用于创建容器。

容器(Container)

  • 定义:容器是镜像的运行实例。容器是独立的、可移植的,并且可以在任何支持 Docker 的地方运行。容器添加了额外的可写层和执行环境。
  • 用途:容器用于运行应用程序,确保应用程序及其依赖项在各种环境中一致运行。每个容器都是从镜像创建的,并在其上增加了一层可写层。
  • 生命周期:容器可以启动、停止、删除和重启。容器的状态可以是运行、停止或退出。

镜像和容器的关系

  1. 创建容器
    • 容器是从镜像创建的。使用 docker run 命令可以从指定镜像创建并启动一个新的容器。
    • 示例:docker run -it ubuntu bashubuntu 镜像创建并启动一个新的容器,并在其中运行 bash
  2. 只读和可写
    • 镜像是只读的。当容器从镜像创建时,会在镜像的基础上添加一个可写层,这样容器中的更改不会影响原始镜像。
    • 容器运行时,可以对文件系统进行更改,这些更改只保存在容器的可写层中。
  3. 一致性
    • 由于镜像包含了应用程序运行所需的一切,所以容器可以在任何支持 Docker 的系统上运行,确保了环境的一致性。
  4. 镜像的构建和层
    • 镜像可以通过 Dockerfile 构建。Dockerfile 是一个包含构建镜像步骤的脚本文件。
    • 每个构建步骤创建一层,所有这些层共同构成最终的镜像。镜像的层是共享的,可以复用,节省存储空间。

宿主机

  • 定义:宿主机是运行容器的物理或虚拟机。宿主机提供了操作系统层面支持,使得容器能够运行。在大多数情况下,宿主机提供了Docker Engine或其他容器运行时环境,这些环境能够管理容器的生命周期。
  • 类比:把宿主机比作餐厅厨房,厨师(Docker Engine或其他容器运行时)在这里准备食材(镜像),然后烹饪成菜肴(容器)供客人享用。
既然要创建镜像,那我们一定要知道什么是dockerfile

二、Dockerfile

2.1 什么是Dockerfile

Dockerfile 是一个文本文件,它包含了一系列的指令和参数,这些指令和参数定义了如何从一个基础镜像构建出一个新的 Docker 镜像。
每个指令通常创建镜像的一个新层,并对镜像进行修改。最终,Dockerfile 描述了完整的步骤,以及如何配置和运行在容器中的应用程序。
编写 Dockerfile 的过程就是定义必要的环境、复制所需文件、安装依赖项、配置运行时等步骤,以确保容器化的应用程序能够正确运行的过程。

2.2 Dockerfile中的常见指令

  • FROM:定义了使用哪个基础镜像开始构建过程。
  • WORKDIR:设置工作目录,即接下来的指令执行的位置。
    - COPY:复制文件或目录到容器内。
  • ADD:与 COPY 类似,但可以处理远程URL和自动解压缩。
  • RUN:执行命令并创建新的镜像层,用于安装软件包等。
  • CMD:提供容器启动时默认执行的命令。
  • ENTRYPOINT:配置一个容器启动时要运行的命令,允许将容器当作可执行程序。
  • EXPOSE:声明容器监听的端口。
  • ENV:设置环境变量。
  • ARG:定义构建时的变量。
  • VOLUME:定义匿名卷,可以在容器之间或容器和宿主机之间共享数据。
  • USER:设置运行容器时的用户名或UID。
  • LABEL:添加元数据到镜像,如作者、版本、描述等。
  • ONBUILD:当一个镜像被用作另一个 Dockerfile 的基础时执行的命令。
  • HEALTHCHECK:告诉 Docker 如何测试一个容器,以检查它是否仍在正常工作。

2.3Dockerfile实例

这个是自己某个diy项目中的Dockerfile:

# 这行指定了基础镜像 node 的版本为 21.6.2,
并且给这个构建阶段命名为 builder。这个基础镜像包括了Node.js运行环境及npm(Node包管理器)。
FROM node:21.6.2 as builder

# 将工作目录设置为容器内的 /app。后续的指令都会在这个目录下执行。
WORKDIR /app

# 这行将宿主机上的 package.json 和 package-lock.json 文件
# 复制到容器的当前工作目录下(/app)。这两个文件定义了项目依赖。
COPY package.json package-lock.json ./

# 安装项目依赖
RUN npm install

# 接着,复制当前目录下的所有内容到容器的工作目录。
# 由于之前已经添加了 package.json 和 package-lock.json,
# 这里通常会排除这两个文件和其他不需要的文件,比如通过 .dockerignore 文件。
COPY . .

# 构建应用程序
# 启动构建过程,并生成最终的静态文件。这些构建好的文件通常被放置在 dist 目录下。
RUN npm run build

# 使用官方的 Nginx 作为基础镜像
# 开始新的构建阶段,并使用 nginx 官方镜像作为基础。
# 这意味着前面的 builder 阶段完成后,这个新阶段开始时会从一个全新的Nginx镜像开始。
FROM nginx

# 从前一个阶段,也就是 builder 中复制 dist 目录下的所有内容到Nginx容器的 /var/www/html。
# 这是Nginx默认的文档根目录,存放静态文件供客户端访问。
COPY --from=builder /app/dist /var/www/html

# 将宿主机上的 nginx.conf 配置文件复制到容器的 /etc/nginx/conf.d/default.conf。
# 这会覆盖Nginx容器默认的配置文件。
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 声明容器在运行时会监听端口80。
# 虽然 EXPOSE 指令本身不会发布端口,但它作为镜像元数据存在,告诉使用该镜像的人应该发布哪个端口。

EXPOSE 80

# 启动 Nginx
# 设置容器启动时默认执行的命令,即启动Nginx服务。
# 这里 -g "daemon off;" 参数确保Nginx在前台运行,而不是作为守护进程。

CMD ["nginx", "-g", "daemon off;"]

2.4 详细扩展

(这一块时间原因,有空更新)

三、镜像

3.1 镜像的创建

在上述Dockerfile书写好以后,运行对应命令

docker build -t my-web-app .

其中 -t my-web-app 是你为镜像指定的名称。
如果运行顺利,咱们使用查看指令

docker image ls

在这里插入图片描述

3.2对于镜像的一些常用命令

对于构建命令,最后的点别忘了带上,仔细看。
下面myimage:latset是指镜像的命名:标签,不要直接复制哦,记得要替换成自己的使用

不带命名直接构建镜像
docker build .  

使用 -t 选项来命名你的镜像
构建出的镜像命名为 myapp 且标签为 1.0。如果你不提供标签,则默认会给镜像打上 latest 标签。
docker build -t myapp:1.0 .   

查看本地所有镜像
docker image ls

显示一个镜像变更的历史
docker history myimage:latest

显示一个或多个镜像的详细配置信息和层次结构。
docker inspect myimage:latest

删除镜像
docker rmi myimage:latest

如果你开始忘了给镜像命名,先ls查看他的image ID,再使用下述命令
            image ID     命名:标签
docker tag 1e0626aac7f4 myapp:latest

还有很多命令,后续实践中使用到我会补充。
关于镜像标签,我在这稍微聊聊

3.3镜像标签的作用

在 Docker 中,虽然不同的标签可以引用同一个镜像,但通常我们会利用标签来区分不同版本的镜像。这是通过构建带有指定标签的新镜像版本,并推送到仓库来实现的。每次应用更新或代码变更,你都会构建一个新的镜像,并给它一个新的版本号作为标签。

例如,你可能有一个应用的多个版本的镜像,如下所示:

docker build -t myapp:1.0.0 .
docker build -t myapp:1.0.1 .
docker build -t myapp:1.1.0 .

这里,1.0.0、1.0.1 和 1.1.0 是不同版本的标签,它们对应于不同版本的应用。每个标签都指向了在特定时间点构建的唯一镜像。

同时,为了方便用户始终能够拉取最新版本的镜像,还可以额外提供一个 latest 标签。在大多数情况下,latest 标签用于指向最新稳定版本的镜像。在发布新的稳定版本时,除了给该版本打上具体的版本号标签之外,还会更新 latest 标签以指向它:

docker build -t myapp:1.2.0 .
一个镜像可以有多个标签
docker tag myapp:1.2.0 myapp:latest

在这种情况下,即使 myapp:latest 和 myapp:1.2.0 标签指向同一个镜像,用户可以选择使用 latest 来始终保持使用最新版,或者使用具体的版本标签 1.2.0 来固定在特定版本。

总结一下,分版本涉及以下步骤:

  • 构建不同版本:每次应用程序更新,你构建一个新的镜像版本。
  • 使用标签区分:为每个镜像构建赋予一个独特的版本号标签。
  • 可选地维护 latest 标签:让 latest 标签始终指向最新的稳定版本镜像。

通过这种方式,你能清晰地管理和分发不同版本的 Docker 镜像。

四、容器

4.1 创建一个容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
  • [OPTIONS] 是可选参数,例如 -d 用于后台运行,-p 用于端口映射,–name 来指定容器名称等。
  • IMAGE 是你想要运行的镜像的名称。
  • [COMMAND] 是启动后在容器内执行的命令。
  • [ARG...] 是传递给命令的额外参数。

例子
假设你想要从 ubuntu 镜像创建一个容器,你可以执行以下命令:

docker run -it --name myubuntu ubuntu /bin/bash

这条命令会做以下几件事情:

  • -it 保证你能够以交互模式连接到容器的终端。
  • –name myubuntu 给你创建的容器指定了一个名字 “myubuntu”。
  • ubuntu 指定了你将要使用的镜像名称。
  • /bin/bash 是在容器内部运行的命令,这里让你进入了 bash shell。

如果你想要在后台运行一个容器,可以使用 -d(detached)选项:

docker run -d --name mynginx -p 80:80 nginx

在这个例子中:

  • -d 指定容器在后台运行。
  • –name mynginx 给容器指定了一个名字 “mynginx”。
  • -p 80:80 表示将容器的 80 端口映射到宿主机的 80 端口上。
  • nginx 是镜像名称,这个命令会启动一个 Nginx web 服务器。

要记住的是,在运行 docker run 命令时,如果本地没有指定的镜像,Docker 会去配置的镜像仓库下载它。一旦使用 docker run 创建了容器,并且容器停止后,你可以使用 docker start 命令再次启动它,而无需重新创建一个新的容器。

docker run --rm -it ubuntu /bin/bash

这条命令将创建并运行一个基于 ubuntu 镜像的容器,并提供一个交互式 bash shell。当你退出 bash(例如,通过键入 exit 命令或使用快捷键 Ctrl+D)时,容器将停止运行,且因为有 --rm 选项,它将立即被自动删除。

4.2 和容器相关的命令

查看所有活动中的容器
docker ps
查看所有容器,无论是否活动中
docker ps -a


启动容器
docker start <container_name_or_id>
例:docker start mycontainer

停止容器
docker stop 容器名/id
例:docker stop mycontainer
立马强制停止
由于 -t 0 的设置,Docker 不会等待任何宽限期,如果容器没有立即正常停止,
Docker 会立刻进行强制停止操作,可能会丢失数据
docker stop -t 0  my_temp_container

进入容器
以下是进入容器的一般命令,其中 -it 参数结合了两个选项:-i(或 --interactive)保持 STDIN 开放即使没有附加,-t(或 --tty)为该命令分配一个伪终端:
docker exec -it <container_name_or_id> /bin/bash
这里 <container_name_or_id> 是你想要进入的容器的名称或 ID,
而 /bin/bash 是在容器内部要运行的命令,
此例中是 Bash shell。如果容器内部没有安装 Bash,
你可能需要尝试使用 /bin/sh 或其他可用的 shell 程序。

如果成功,你会看到命令提示符变为容器内部的环境,例如:
root@a1b2c3d4e5f6:/#
可以输入 exit 来退出容器的 shell 环境。

4.3 容器端口或文件挂载宿主机

端口映射
端口映射允许从本地主机访问容器内部应用程序。你可以在 docker run 命令中使用 -p 或者 --publish 参数设置端口映射。

示例:端口映射

docker run -d \
  --name webserver \
  -p 8080:80 \
  nginx:latest

这条命令会启动一个新的 Nginx 容器,并将容器内部监听的 TCP 端口 80 映射到宿主机的 TCP 端口 8080 上。这意味着你可以通过访问宿主机的 8080 端口来访问 Nginx 服务器。

挂载文件
在 Docker 中,有两种主要的方式来挂载文件和目录到容器中:–mount-v(或 --volume)

使用 --mount 标志
–mount 是 Docker 引入的较新的挂载选项,它具有更严格的规范格式。它通常被推荐用于新的部署和脚本,因为其语法更明确且更易阅读。

docker run -d \
  --name devtest \
  --mount type=bind,source="$(pwd)"/html,target=/usr/share/nginx/html \
  nginx:latest

这里的参数:

  • type=bind 表示这是一个绑定挂载。
  • source=“$(pwd)”/html 指定了宿主机上要挂载的目录路径。
  • target=/usr/share/nginx/html 指定了容器内的挂载点。

使用 -v 或 --volume 标志
-v 或 --volume 标志是 Docker 较早期的挂载选项,它允许简写形式和较灵活的路径表示方法。虽然它不像 --mount 那样规范,但仍然广泛用于很多 Docker 运行实例中。

docker run -d \
  --name mynginx \
  -v "$(pwd)"/html:/usr/share/nginx/html \
  nginx:latest

在这个 -v 参数中:

  • “$(pwd)”/html 是宿主机上的目录路径。
  • /usr/share/nginx/html 是容器内的挂载点。

因此,为确保一致性以及避免混淆,你应当选择 --mount 或 -v 其中的一种,并且在部署过程中坚持使用同一种方式。如果你喜欢更明确且详述的风格,那么 --mount 可能是更好的选择;如果你偏好简短的命令,或者是需要维护旧的脚本,则可能会倾向于使用 -v。(我个人偏好-v)

(有空继续更新,docker的安装网上很多xdm自行去搜就好了)

;