我们将通过 Node.js 中的示例深入了解 Docker 的基础知识,以了解它的好处。您可以在此处从本文下载工作代码示例。

当我们谈论软件时,它包括一整套组件,包括前端和后端组件、数据库、库等。

在我们的软件部署期间,我们必须确保所有这些组件都可以在我们的应用程序可能运行的各种平台上工作。

Docker是干什么用的?

[:)](https://res.cloudinary.com/practicaldev/image/fetch/s--6Trt3dZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/ed3oqwu87l8g1rlpck29.png)

我猜你遇到过在本地测试你的应用程序的情况,在部署它时,有些东西没有按预期工作。

Docker 通过打包应用程序及其所有依赖项并在隔离环境中运行来简化部署应用程序的过程来解决这个问题,从而使该过程变得非常简单和高效。

虽然 Docker 可以存在于软件开发的整个工作流程中,但它的主要用途是在部署期间。

这样,Docker 将您的应用程序分隔在这个我们称为容器的标准化单元中。

什么是容器?

请记住,我们说过 Docker 在隔离环境中打包和运行您的应用程序。这就是我们所说的容器。

容器提供了一种打包机制,在这种机制中,应用程序可以从它们实际运行的环境中抽象出来,从而使开发人员能够创建可预测的环境。 容器成为测试应用程序的单元

为什么选择Docker?

Docker 与虚拟机

虚拟机(VM)是物理硬件的抽象,将一台服务器变成多台服务器。虚拟机管理程序是创建和运行 VM 的计算机软件、固件或硬件,允许其中几个在单个机器上运行。每个 VM 都包含操作系统内核、应用程序和必要库的完整副本。 VM 的启动速度也可能很慢。

kernel 是操作系统的一部分,它处理内存管理、资源分配和其他对系统至关重要的低级服务。

[Docker 与 VM](https://res.cloudinary.com/practicaldev/image/fetch/s--SNnndKpa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro. medium.com/max/1050/0%2AFYLf2FmgeMdEN9QA.png)

容器和虚拟机具有相似的资源隔离和分配优势,但功能不同,因为容器虚拟化的是操作系统而不是硬件

容器是应用层的抽象,将代码和依赖项打包在一起。多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器都作为用户空间中的独立进程运行。

Docker的好处

从运营的角度来看,它可以提高您的基础架构效率,从而更好地利用计算资源。与使用虚拟机相比,这使我们能够在给定的硬件组合上运行更多的容器。

回到容器,容器是 Docker 映像的运行时实例。所以基本上,一个 Docker 容器由一个 Docker 镜像、一个执行环境和一组标准指令组成。但是,什么是图像?

什么是图像?

正如我们所见,容器是镜像的可运行实例。因此,与容器不同,图像没有状态并且永远不会改变。映像是一个模板,其中包含创建 Docker 容器的说明

从这里开始,我们将按照存储库中的示例来构建我们的节点应用程序并对其进行 dockerise。

首先,我们有一个 index.js 文件,它公开一个 get 并返回我们运行应用程序的端口。我们需要安装 express 和 dotenv 作为此示例的依赖项。

如果我们运行应用程序并浏览http://localhost:3000服务器将返回

Your application is running on port 3000

进入全屏模式 退出全屏模式

那么接下来的问题是,我们如何构建 Docker 镜像?

Dockerfile 有什么用?

对于构建图像,我们使用 Dockerfile。这是一个带有简单语法的文件,用于定义创建和运行图像所需的步骤

通常,它是一个图像基于另一个图像,并带有一些额外的定制。这就是 Dockerfile 包含的内容。因此,为了组装我们的镜像,我们将创建一个文档,其中包含构建我们自己的应用程序镜像所需的所有命令。

我们可以创建自己的图像,也可以使用他人创建并发布在注册表中的图像。例如,我们可以使用在 Docker Hub 上发布的任何镜像。

我们将构建节点应用程序的映像。为此,我们可以从 FROM 一个 Ubuntu 映像开始,在其上安装 Node,然后再安装我们的应用程序,或者直接从 Node 映像启动。

Dockerfile 中的每条指令都会在镜像中创建一个层,当您更改 Dockerfile 并重建镜像时,只有那些已更改的层才会被重建。这就是使图像如此轻巧、小巧和快速的原因。

我们将从 FROM 一个 Node 映像开始,并从那里安装并运行我们的应用程序,如下所示:

在此之后,我们有 RUN 一对命令。第一个安装 Python 作为构建依赖项。这个项目的依赖是不必要的,但它是一个很好的例子来看看如何插入构建依赖,也就是说,我们需要构建我们的应用程序,但是一旦程序被编译,我们就不再需要它了。第二个安装项目的依赖项。

在这些示例中,我们在源代码 (COPY . .) 之前 COPY package.json。这是因为 Docker 镜像是由层组成的,并且由于文件 package.json 不会像我们的源代码那样经常更改,我们不想在每次运行docker build时都重新构建我们的 node_modules

我们将 ENV 变量 PORT 设置为 3000 和 TYPE,以便我们在运行 dockerised 应用程序时看到差异。

之后,EXPOSE 告诉 Docker 容器在运行时正在监听哪个端口,在本例中,我们公开了 3000 端口。

最后,CMD 命令告诉 Docker 如何运行我们打包在镜像中的应用程序。 CMD 遵循 CMD [“command”, “argument”] 格式。

如果我们现在运行命令docker build .,我们将构建刚刚创建的映像。如果我们想标记我们刚刚创建的图像,我们也可以运行docker build --tag myapp .

我们现在可以看到我们刚刚使用命令docker images构建的映像。

为了提高构建的性能,我们应该通过向该目录添加一个.dockerignore文件来避免文件和目录包含在映像中。在我们的例子中,我们忽略了所有不需要的文件。

我们现在可以运行docker run -p 3001:3000 myapp。这样,我们将主机端口 3001 映射到容器端口 3000。模式是HOST:CONTAINER

所以现在,当我们访问http://localhost:3001时,服务器现在将返回:

Your built with Dockerfile application is running on port 3000

进入全屏模式 退出全屏模式

docker-compose 是干什么用的?

想象一下,我们想要运行两个容器,一个用于我们的节点应用程序,另一个用于我们将存储一些信息的数据库,例如 MongoDB。这是 docker-compose 变得有用的时候。

docker-compose 定义了一个docker run命令。这是创建和运行我们的容器的一组步骤。我们在单个文件中定义了一个多容器应用程序,然后在一个命令中启动我们的应用程序,该命令完成了运行所需的所有操作。

首先,确保你在你的机器上安装了 docker-compose 并添加了这个 docker.compose.yml 文件:

我们在这里给出了构建两个映像的说明,一个用于 myapp,另一个用于 mymongo

在服务 myapp 中,我们告诉 docker-compose 使用同一目录中的 Dockerfile(build .中的 . 表示运行构建命令,Dockerfile 位于当前工作目录中)。

我们还告诉 myappdepends_onmymongo,所以 myapp 在 mymongo 运行之前不会运行。

使用ports指令,我们再次将暴露的端口映射到 3001,就像我们之前手动对docker run命令所做的那样。

我们设置 environment 变量 PORT 和 *TYPE 以便当我们运行命令docker-compose并检查http://localhost:3001时,我们应该看到:

Your built and run with docker-compose application is running on port 3000

进入全屏模式 退出全屏模式

命令docker-compose up为 Docker 提供了根据 docker-compose.yml 构建镜像和运行容器的指令。

命令docker-compose down关闭了之前脚本运行的所有服务。

由于docker ps列出了 Docker 引擎中所有正在运行的容器,而docker-compose ps列出了与docker-compose file中声明的镜像相关的容器,因此docker-compose ps的结果是docker ps的结果的子集。

Docker 命令行备忘单

以下是一些有用的 Docker 命令解释:

docker build --tag tagname .→ 从当前目录的 Dockerfile 构建镜像并标记镜像。示例: docker build --tag myapp 。

docker run -d -p 80:80 tagname service nginx start→ 示例:docker build --tag myapp。

docker ps→ 检查正在运行的容器。

docker ps -a→ 显示所有容器(默认只显示正在运行的容器)。

docker exec -it containername bin/sh→ 从给定的 docker 容器进入控制台。

docker images→ 查看本地构建的图像

docker images -a→ 查看本地存储的所有图像,甚至包括中间图像。请记住,每个 Docker 映像都由层组成,这些层彼此之间具有父子层次关系。 Docker 将此称为中间映像。

docker image rm imagename→ 删除图像。

docker stop containername→ 停止容器。

docker rm containername→ 取出容器。

docker-compose -f path/to/docker-compose.yml up→ 创建并启动在 docker compose 文件上指定的容器。示例:docker-compose -f docker/docker-compose.yml up

docker-compose -f path/to/docker-compose.yml down→ 停止并移除容器、网络、图像和卷。示例:docker-compose -f docker/docker-compose.yml down

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐