Docker:简化应用程序开发的最终指南
#node #docker #containers #dockerhub

近年来,Docker已成为希望简化其应用程序开发过程的开发人员的流行工具。在这篇博客文章中,我们将深入研究Docker的基础知识,包括其核心组件以及与虚拟机的比较。我们还将涉及关键术语和概念,这些术语和概念将帮助您了解Docker如何彻底改变您的工作流程。

Docker

现在什么是Docker?

Docker是一个平台,旨在简化建筑物,运行和运输应用程序的过程。它通过利用容器化技术来实现这一目标,该技术使开发人员可以为运行应用程序创建称为容器的孤立环境。

想象您正在搬到新房子,并且有一个带有特定家具,装饰和设置的房间,您想在新地方重新创建。单独运输所有物品,确保没有损坏任何东西,然后在新房子中再次设置所有东西可能是一个乏味且耗时的过程。

在这种情况下,将Docker视为便携式房间,您可以将其用来将所有物品包装在一起。 Docker允许您将家具,装饰品和设置放入容器中,然后将其密封并运送到新房子,而不必担心兼容性或损坏。到达后,您只需“解开”容器,您的房间就完全按原样设置了。

在软件开发领域,Docker以类似的方式工作。应用程序通常取决于特定的库,配置和运行时环境。手动对不同系统(例如开发,测试和生产环境)手动设置这些依赖项可能会很复杂且耗时,并可能导致不一致或错误。

Docker容器封装了应用程序需要运行的所有内容,包括操作系统,库,依赖项和应用程序代码。这确保了应用程序在不同环境中始终如一地运行,而不论基础系统如何。使用Docker,开发人员可以一次构建一个容器,然后将其部署到开发过程的各个阶段(例如测试,分期和生产),而不必担心兼容性问题或差异。

总而言之,就像便携式房间使您能够轻松,一致地在房屋之间移动物品一样,Docker使开发人员能够在各种环境中始终构建,运行和运输应用程序,从而简化部署过程并减少潜在错误。

Container

容器与虚拟机

虽然容器和虚拟机(VM)在孤立的环境中启用运行应用程序,但它们的基础体系结构和资源消耗都有很大差异。

虚拟机是硬件资源的抽象,由虚拟机管理程序(例如VirtualBox,VMware或Hyper-V(仅Windows))创建和管理。 VM效仿了一个完整的系统,包括操作系统,并且可以是资源密集型且开始缓慢的系统。

另一方面,容器轻巧并快速启动,因为它们不包括成熟的操作系统并共享主机的操作系统,尤其是内核,只需要使用自己的文件系统一个操作系统流程。与VM相比,这会导致更有效的资源利用和更快的启动时间。

内核是操作系统的核心组成部分,负责管理应用程序和硬件资源。

container vs Vm

Docker架构

Docker使用客户端服务器体系结构进行操作,该体系结构由客户组件和通过REST API通信的服务器组件组成。该服务器(也称为Docker Engine)在后台运行,处理构建和运行容器的任务。 Docker确实有以下组件:

docker客户端: docker客户端是用户与docker交互的主要接口。它提供了一个命令行接口(CLI),并允许用户发布命令以构建,运行和管理容器。客户通过RESTFULE API与Docker Daemon(或Docker Engine)进行通信,以执行各种任务,例如创建容器,拉图像和管理容器生命周期。除了CLI外,Docker还提供了用于Windows和MacOS用户的Docker Desktop的图形用户界面(GUI),这使得更易于视觉管理容器和图像。

docker守护程序(发动机):码头守护程序(也称为Docker Engine)是一个背景过程,可在主机机器上运行并管理容器的整个生命周期。守护程序从Docker客户端聆听API请求,并执行所需的任务,例如构建图像,创建容器和管理容器生命周期。它负责在Docker系统中执行实际工作,包括管理集装箱隔离,网络和存储。

docker图像: docker图像是容器的构建块。它们是仅包含操作系统,运行时环境,库和应用程序代码的仅阅读模板。图像可以从Dockerfile创建,该脚本包含用于构建图像的说明。可以通过Docker注册表(例如Docker Hub或私人注册表)存储和共享Docker图像,从而使用户可以轻松地在不同的环境中分发和部署应用程序。

docker容器: docker容器是用于运行应用程序的轻巧,便携式和隔离的运行时环境。它们是由Docker Images创建的,并在图像顶部具有可写的层,这使他们可以存储运行时数据并维护其状态。容器相互隔离,仅共享主机的内核,这使其与虚拟机相比高效。可以使用Docker命令来轻松管理容器,例如Docker Start,Docker Stop和Docker RM。

docker网络:
Docker提供了一个强大的网络模型,该模型可以在容器与外界之间进行通信。它支持多个网络驱动程序,例如桥梁,主机,叠加层和麦克弗兰,它们提供了不同级别的隔离和性能。默认情况下,Docker创建了一个称为桥梁网络的虚拟网络,该网络允许容器彼此和主机进行通信。用户还可以创建自定义网络以隔离容器或将其连接到外部网络。

docker卷和存储:
Docker提供了一个灵活的存储系统,用于管理容器中的数据。它支持各种存储驱动程序,例如Overlay2,AUFS和BTRF,这些驱动程序确定了如何在主机系统上存储和管理数据。 Docker还支持卷,这是一种持久由容器生成并在容器之间共享数据的方法。可以使用Docker命令来管理卷

Docker注册表:存储和共享Docker图像的存储库。 Docker Hub是最受欢迎的注册表,为存储和分发图像提供了一个平台。

docker容器与图像

Docker术语中的一个基本区别是容器和图像之间的差异。图像是一个仅读取模板,其中包括运行应用程序所需的操作系统,运行时环境,库和应用程序代码。另一方面,容器是图像的运行实例。当从图像创建容器时,添加了一个可写的图层,允许容器存储运行时数据并维护其状态。

安装Docker

要在计算机上安装Docker,请按照操作系统的官方安装指南:

Docker容器生命周期

Docker容器的生命周期通常由几个阶段组成:

创建:使用docker createdocker run命令创建一个容器。创建时,容器具有Docker Daemon分配的唯一ID。

开始:可以使用docker start命令启动创建的容器,也可以使用docker run在单个命令中创建并启动它。启动后,容器运行DockerFile中指定的入口处命令(或docker run命令中提供的自定义命令)。

暂停/简历:可以使用docker pause命令暂停容器,该命令暂时暂停容器内的所有进程。要恢复暂停的容器,请使用docker unpause命令。

停止:可以使用docker stop命令停止运行容器。此命令将 sigterm 信号发送到容器内部的主过程,从而使其可以执行优雅的关闭。宽限期之后,如果容器尚未退出,则发送 sigkill 信号以有力终止容器。

重新启动:可以使用docker restart命令重新启动停止的容器,该命令会停止并再次启动容器。

删除:可以使用docker rm命令去除不再需要的容器。这将永久删除容器及其可写的层,从而释放了系统资源。

Docker lifecycle

开发工作流程

  • 编写应用程序代码并创建一个Dockerfile:首先编写您的应用程序代码并创建一个定义用于构建Docker Image的说明的Dockerfile

Dockerfile是一个文本文件,其中包含Docker使用的一系列指令来构建新图像。它自动化设置环境,安装依赖项并在容器中配置应用程序的过程。 Docker从Dockerfile读取说明并按顺序执行它们,从而创建一个新图像。

  • 构建docker映像:使用docker build命令从dockerfile创建docker映像。

  • 运行容器:使用Docker Run命令从Docker Image启动一个容器。

  • 测试应用程序:测试在容器内运行的应用程序,以确保其按预期运行。

  • 发布Docker映像:如果应用程序按预期工作,请将Docker Image发布到Docker Hub等注册表。

  • 部署容器:使用Docker Compose,Kubernetes或其他编排平台等工具将容器部署到所需的环境中。

dockerizing node.js应用程序

创建一个node.js应用程序:首先创建一个使用app.js文件和package.json文件的简单node.js应用程序。

这是一个简单的node.js应用程序,可提供“ Hello,World!”端口3000上的消息。

  • 首先,请确保您在系统上安装了node.js。如果没有,您可以从官方Node.js网站下载并安装它。

  • 为您的node.js应用程序创建一个新目录,然后在终端或命令提示符中导航到它。

  • 通过运行以下命令:
    初始化一个新的node.js项目

npm init -y

这将创建一个带有默认值的package.json文件。

  • 在项目目录中创建一个名为app.js的新文件,并添加以下代码:
const http = require('http');

const hostname = '0.0.0.0';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

此代码创建了一个基本的HTTP服务器,该服务器在端口 3000 上听,并以“ Hello,World!”做出响应。对于任何传入的请求。

  • 更新package.json文件以包含一个启动脚本。将以下行添加到脚本部分:
"start": "node app.js"

您的软件包文件现在应该看起来像这样:

{
  "name": "your-project-name",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

要在本地运行node.js应用程序,请执行以下命令:
npm start
您应该在终端中看到"Server running at http://0.0.0.0:3000/"的消息。打开您的网络浏览器,然后导航到http://localhost:3000/查看“ Hello,World!”消息。

现在您有了一个简单的node.js应用程序,您可以继续创建一个dockerfile并将其扩展到应用程序。

创建一个Dockerfile:

在与Node.js应用程序同一目录中,创建一个具有以下内容的DockerFile:

# Set the base image
FROM node:latest

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json to the working directory
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the application code to the working directory
COPY . .

# Expose the application port
EXPOSE 3000

# Start the application
CMD ["npm", "start"]

此DockerFile使用最新的官方node.js映像作为基础,将工作目录设置为 /app,复制package.json和package-lock.json文件,安装所需的依赖项,复制应用程序代码,公开端口端口3000,并运行NPM启动命令。

这是Dockerfile中使用的一些常见说明的简要概述:

来自:指定要用作新图像的起点的基本图像。示例包括Ubuntu,Alpine或Node等官方图像。 FROM node:latest

workdir :设置容器中的工作目录。使用相对路径的任何后续指令将相对于此目录执行。 WORKDIR /app

复制:将文件或目录从本地计算机(构建上下文)复制到容器的文件系统。 COPY package.json .

add :类似于复制,但它也可以从URL下载文件并提取压缩文件。 ADD https://example.com/file.tar.gz /app

运行:在容器中执行命令,通常用于安装软件包或运行构建脚本。 RUN npm install

cmd :提供启动容器时运行的默认命令。如果用户在运行容器时指定命令,则将覆盖此默认命令。 Dockerfile中只能有一个CMD指令。 CMD ["npm", "start"]

entrypoint :类似于CMD,但是当用户在运行容器时指定命令时,它不会被覆盖。这对于定义容器的默认可执行文件很有用。

ENTRYPOINT ["npm"]
CMD ["start"]

env :在容器内设置一个环境变量,可以通过在容器内运行的应用程序使用。 ENV NODE_ENV=production

公开:通知Docker,该容器在运行时在指定的网络端口上听。这实际上并未发布端口;它用作文档,并提醒运行容器时使用-P标志发布端口。 EXPOSE 80

音量:为容器外部的数据持续存在一个安装点。这对于删除容器时在容器之间共享数据或保留数据很有用。 VOLUME /app/data

  • 构建Docker映像:在终端中运行以下命令:
docker build -t your-image-name .

用图像的描述名称替换您的图像名称。

  • 运行Docker容器:使用以下命令启动容器:
docker run -p 3000:3000

将此Docker图像推到Docker Hub

Docker Hub是一项公共注册表服务,可让您存储和共享Docker图像。要将Docker图像推到Docker Hub,您需要按照以下步骤操作:

创建一个Docker Hub帐户:如果您还没有Docker Hub帐户,请在注册一个帐户。您需要Docker ID和密码以进行后续步骤。

登录Docker Hub:打开终端或命令提示

docker login

提示时输入您的Docker ID和密码。您应该看到一条消息,表明您已成功登录。

标记您的Docker映像:在将图像推向Docker Hub之前,您需要使用Docker Hub用户名和存储库名称标记它。使用以下命令标记您的图像:

docker tag your-image-name your-docker-id/your-repository-name:your-tag

用您在步骤4中构建的图像的名称替换您的图像名称,带有Docker Hub用户名,带有所需存储库名称的您的repository-name,并带有一个版本的标签或任何描述性标签(例如,'最新')。

例如:

docker tag myapp-image johnsmith/myapp:latest

将Docker图像推到Docker Hub:最后,使用以下命令将标记的图像推到Docker Hub:

docker push your-docker-id/your-repository-name:your-tag

用步骤5中使用的值替换您的docker-id,repository-name和您的标签。Docker会将您的图像上传到Docker Hub帐户。
例如:

docker push johndoe/myapp:latest

验证Docker Hub上的图像:登录到您的Docker Hub帐户并导航到“存储库”部分。您应该看到存储库下列出的新推出的图像。
现在,您的Docker映像已成功地推到Docker Hub,并且可以使用docker pull命令轻松地将其拉动和运行,然后是docker run

Docker容器的好处

Docker容器提供了比传统部署方法和虚拟机的几个优点:

一致性:容器包装所有应用程序依赖性和配置,确保从开发到生产的各种环境的一致行为。

隔离:容器在孤立的环境中运行,防止冲突并确保每个应用程序都可以访问其所需的资源。

可移植性: Docker图像可以轻松地在任何系统上使用Docker安装在任何系统上运行,从而易于在不同平台上部署应用程序。

资源效率:容器共享主机操作系统的内核和资源,与虚拟机相比,间接费用较小。这可以实现更高的密度和更有效的资源利用。

可伸缩性:可以轻松地将容器缩放或向下缩放以满足应用程序不断变化的需求,从而更容易构建和部署微服务和分布式应用程序。

版本控制和回滚: docker映像可以版本化,可以在需要时轻松回滚到以前的版本。对于引入错误或性能问题的应用程序更新,这可能特别有用。

总而言之,Docker容器为应用程序部署提供了有效,便携式且一致的环境。通过利用容器化,开发人员和运营团队可以简化开发,测试和部署流程,最终导致更可靠和可维护的软件。