面向Web开发者的Docker介绍

98 阅读9分钟

针对网络开发者的Docker介绍

知道如何在应用程序开发中使用容器是现代开发者的必修课。最近对容器的需求的一个原因是Docker的出现。Docker不仅增加了容器的使用,而且对我们处理应用开发的方式产生了很大的影响。

如果你是一个还没有找到这种流行技术的适当介绍的开发者,你就来对了。在这篇文章中,我们将向你介绍Docker的概念,并通过对一个简单的应用程序进行docker化来获得学习Docker的实践方法。

首先,让我们澄清一下什么是Docker以及为什么它变得如此重要。


什么是Docker?

Docker是一个工具,开发者用来通过容器在隔离的环境中创建、部署和运行应用程序。

又来了,容器。虽然这个词从文章开始就被使用了几次,但你可能不知道什么是容器。为了充分理解上述说法,我们首先要理解什么是容器。


什么是容器,我们为什么需要它?

容器是一个软件单元,它将应用的代码和应用中使用的所有依赖关系打包成一个单一的包。包装允许容器将应用程序与它所运行的主机环境隔离。应用程序将容器视为其环境,而不是主机设备。这种抽象性保证了在开发环境中运行的应用程序能够在生产环境中运行,而不需要经历重大的改变。

即使有几个应用程序在主机设备上运行,容器也会将容器化的应用程序隔离开来,不干扰其他应用程序的运行,并分享它们的资源。

在容器之前,虚拟机被用来将应用程序与主机环境隔离。在虚拟机中,每台机器都使用一个单独的操作系统来运行应用程序。虽然这种方法也达到了隔离应用程序的目的,但它的缺点是在应用程序的基础上增加了太多的开销。另一方面,容器共享主机设备的操作系统内核,而不是使用自己的操作系统,这消除了虚拟机所增加的开销。这使得容器与虚拟机相比更加轻巧,资源效率更高。

image.png Docker vs VM

尽管在Docker之前,容器已经被使用了很长时间,但可以说Docker是容器在现代编程领域极度流行的最大原因。除了开源之外,Docker的易用性、可靠性和效率使编程界立刻爱上了这项技术。


什么是Dockerfile、Docker Image和Docker Engine?

Docker有其特殊的语言。Dockerfile、Docker image和Docker engine是Docker用户中常用的三个词。这也是构建Docker容器时使用的3个最重要的组件。

Dockerfile

Dockerfile包含了一套构建Docker镜像的指令,我们接下来要讨论的是这套指令。在创建Docker镜像时,这些指令将被一个接一个地运行。Dockerfile中的指令包含诸如主机设备的操作系统、应用程序的编程语言、应用程序目录位置、网络端口和环境变量等信息。

Docker镜像

Docker镜像是一个模板,用于为应用程序创建最终的Docker容器。我们可以通过运行以Dockerfile为参数的docker build命令来生成一个应用程序的Docker镜像。为了创建Docker容器,我们使用docker run命令和Docker镜像。

Docker引擎

Docker引擎是所有Docker容器运行的地方。基于Windows和Linux的应用程序都可以在Docker引擎上运行。


如何将一个简单的应用程序Docker化

现在,我们已经到了本教程最有趣的部分。我们将对一个简单的应用程序进行dockerize,以获得实际的Docker经验。首先,我们将创建一个简单的Node.js应用程序,然后,创建Docker文件、Docker镜像,最后为应用程序创建Docker容器。

不过,在继续之前,请确保你的设备上已经安装了Docker。你可以按照官方文档在你的WindowsUbuntu操作系统上安装Docker。请查看其他操作系统的文档。

创建一个简单的Node.js应用程序

我们将创建一个简单的Node应用程序,当我们访问根路径时发送一个 "Hello World "消息。

按照这些步骤来设置你的应用程序。

npm init
npm install express --save

在目录内,app.js 文件包含我们的主要应用代码。

const express = require('express')
const app = express()
 
app.get('/', (req, res) => {
    res.send("Hello World!")
})
 
app.listen(process.env.PORT, () => {
    console.log("Node server has started running")
})

为应用程序创建Docker文件

现在我们可以用创建Docker镜像所需的信息来创建Docker文件。

在应用程序目录下创建一个名为Dockerfile 的文件。为了给我们的应用程序创建Docker镜像,Dockerfile应该包含一组这样的命令。

FROM node:latest
 
WORKDIR /docker-tutorial
 
COPY . .
 
ENV PORT 3000
 
RUN npm install
 
EXPOSE $PORT
 
ENTRYPOINT ["node", "app.js"]

现在我们来看看这些命令各自的含义。

  1. FROM-这条命令设置了基础镜像,应用程序的新镜像是在此基础上建立的。在我们的例子中,我们使用一个包含npm和最新Node.js版本的镜像。这个镜像来自Docker Hub,它是一个公共的Docker镜像库。
  2. WORKDIR-这条命令为将在容器中运行的应用程序设置工作目录。
  3. COPY-该命令将应用程序目录中的文件复制到我们用前一条命令设置的工作目录中。你可以传递特定文件名的路径,或者像上面那样把应用程序目录中的所有文件复制到Docker镜像中。在后一种情况下,确保你在运行docker build命令时已经在命令行上导航到应用程序目录。
  4. 环境在Node应用程序中,注意我们如何将环境变量PORT(process.env.PORT)传递给app.listen函数,而不是直接传递应用程序应该监听的端口号。因此,我们必须在应用环境中设置PORT环境变量。对于我们的应用程序来说,它将进入Docker容器。因此,我们使用ENV命令来传递我们想在Docker容器内设置为环境变量的变量。
  5. RUN-这个命令运行npm install来安装我们应用程序中使用的依赖,这些依赖被保存到package.json文件中。
  6. EXPOSE-该命令将应用程序暴露在给定的端口上。由于我们已经将端口号设置为环境变量,我们传递变量名称$PORT,以代替实际的端口号。然而,请记住,应用程序被暴露在容器环境中的3000端口,而不是主机设备的环境。
  7. ENTRYPOINT-这条命令设置了如何进入,或者说如何启动我们的应用程序。Docker将我们传递的数组连接起来,创建一个启动应用程序的单一命令,也就是node app.js。

构建Docker镜像

我们使用docker build命令,从Docker文件中构建Docker镜像。以下是它的工作原理。

docker build -t <image-name> <dockerfile-location>

在运行该命令之前,请确保你已经在你的命令行上导航到应用程序目录。你可以在Dockerfile的位置上传递一个点(.)来表示Dockerfile在当前目录下。

对于我们的例子,我们将运行。

docker build -t docker-tutorial .

输出。

Sending build context to Docker daemon  2.008MB
Step 1/7 : FROM node:latest
latest: Pulling from library/node
81fc19181915: Pull complete 
ee49ee6a23d1: Pull complete 
828510924538: Pull complete 
a8f58c4fcca0: Pull complete 
33699d7df21e: Pull complete 
923705ffa8f8: Pull complete 
ae06f9217656: Pull complete 
39c7f0f9ab3c: Pull complete 
df076510734b: Pull complete 
Digest: sha256:719d5524c7e927c2c3e49338c7dde7fe56cb5fdb3566cdaba5b37cc05ddf15da
Status: Downloaded newer image for node:latest
 ---> dcda6cd5e439
Step 2/7 : WORKDIR /docker-tutorial
 ---> Running in 8797780960e9
Removing intermediate container 8797780960e9
 ---> b80abb69066b
Step 3/7 : COPY . .
 ---> cc9215d75956
Step 4/7 : ENV PORT 3000
 ---> Running in 4bf08e16b94d
Removing intermediate container 4bf08e16b94d
 ---> 95007721d5ee
Step 5/7 : RUN npm install
 ---> Running in d09f45f0bbd7
npm WARN docker-tutorial@1.0.0 No description
npm WARN docker-tutorial@1.0.0 No repository field.

audited 50 packages in 1.146s
found 0 vulnerabilities

Removing intermediate container d09f45f0bbd7
 ---> 292a854f73e2
Step 6/7 : EXPOSE $PORT
 ---> Running in f2ae755655b3
Removing intermediate container f2ae755655b3
 ---> 6d42325fe934
Step 7/7 : ENTRYPOINT ["node", "app.js"]
 ---> Running in d657168980d8
Removing intermediate container d657168980d8
 ---> 0c6df3f042eb
Successfully built 0c6df3f042eb
Successfully tagged docker-tutorial:latest

一旦你运行docker build命令,Docker将连续执行Dockerfile中的每条命令。当执行FROM命令时,如果Node镜像之前没有被拉到你的设备上,Docker将从Docker Hub拉取镜像。

一旦所有的命令被执行,如果镜像被创建而没有遇到错误,你会看到 "成功构建 "的信息。

你可以使用命令,docker images ,来查看你的设备中目前所有的镜像。

输出。

REPOSITORY       TAG      IMAGE ID        CREATED         SIZE
docker-tutorial  latest   0c6df3f042eb    3 minutes ago   943MB
node             latest   dcda6cd5e439    2 weeks ago     942MB

创建Docker容器

我们使用下面的命令来创建和运行Docker容器,使用已经构建的Docker镜像。

docker run -d -p 8080:3000 docker-tutorial

输出。

a7cc6a41996fa565890b57e292aff5df99cb5e13a8c7ab8cea2506e16d70d01e

这里,-d 标志被用来在守护模式下运行容器。-p标志用于将容器向外界开放的端口映射到应用程序正在监听的端口上。在之前的Docker文件中,我们将内部端口,即应用程序端口,设置为3000。因此,在这里,我们要把容器向主机设备打开的8080端口映射到3000端口。docker-tutorial 是Docker镜像的名称。

你可以使用docker ps 命令查看你的设备上当前运行的Docker容器及其ID。

就这样,我们已经完成了简单的Node应用程序的docker化过程。你可以在你的浏览器上访问网址http://localhost:8080,检查应用程序和容器是否正常工作。如果你已经成功了,你会看到 "Hello World "的信息。(如果你的Docker引擎不是在localhost运行,请用它在你设备上使用的IP地址替换localhost)。

停止和删除Docker容器

如果你想停止一个正在运行的Docker容器,请使用以下命令。

docker stop <first-3-characters-of-the-container-id>

然而,这只是停止了容器,而没有从系统中完全删除它。如果你想重新启动容器,你可以使用带有容器ID的docker start命令。

如果你想完全删除一个停止的容器,可以使用这个命令。

docker rm <first-3-characters-of-the-container-id>

总结

今天,Docker已经成为一项庞大的技术,对每一个开发者来说都是不容忽视的。我们的文章向你介绍了这一流行的技术,解释了什么是Docker,以及用Docker来容器化一个应用程序。我们学习了如何为一个简单的Node.js应用程序创建Docker文件、Docker镜像,以及最后的Docker容器。但这仅仅是Docker的开始。它有更多的功能和高级配置,可以帮助你相当容易和有效地创建、运行和部署应用程序。所以,把这个Docker的介绍作为一个机会,深入研究和探索与Docker有关的更复杂的概念。