欢迎!我们很高兴您想学习Docker。 Docker入门教程教您如何:
Docker是供开发人员和系统管理员使用容器构建,共享和运行应用程序的平台。使用容器部署应用程序称为容器化。容器不是新的,但用于轻松部署应用程序的容器却是新的。
容器化越来越受欢迎,因为容器是:
从根本上说,一个容器不过是一个正在运行的进程,并对其应用了一些附加的封装功能,以使其与主机和其他容器隔离。 容器隔离的最重要方面之一是每个容器都与自己的私有文件系统进行交互。 该文件系统由Docker镜像提供。 镜像包括运行应用程序所需的所有内容 - 代码或二进制文件,运行时,依赖项以及所需的任何其他文件系统对象。
容器在Linux上本地运行,并与其他容器共享主机的内核。 它运行一个独立的进程,不占用比其他任何可执行程序更多的内存,从而使其轻巧。
相比之下,虚拟机(VM)运行成熟的“guest”操作系统,并通过虚拟机管理程序对主机资源进行虚拟访问。 通常,VM会产生大量开销,超出了应用程序逻辑所消耗的开销。
#### 安装Docker Desktop
开始开发容器化应用程序的最佳方法是使用OSX或Windows的Docker Desktop。 Docker Desktop可让您轻松地在本地开发计算机上设置Kubernetes或Swarm,因此您可以立即使用正在开发应用程序的Orchestrator的所有功能,而无需任何集群。 请遵循适合您的操作系统的安装说明:
Docker Desktop将为您快速轻松地设置Kubernetes。 请遵循适用于您的操作系统的设置和验证说明:
注意:本文只是翻译,并不能保证安装成功,kubernetes被墙,需要中国镜像,
apiVersion: v1
kind: Pod
metadata:
name: demo
spec:
containers:
- name: testpod
image: alpine:3.5
command: ["ping","8.8.8.8"]
这描述了具有单个容器的容器,将简单的ping隔离到8.8.8.8。
kubectl apply -f pod.yaml
kubectl get pods
您应该看到类似以下内容:
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 0 4s
kubectl logs demo
您应该看到一个健康的ping过程的输出:
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=37 time=21.393 ms
64 bytes from 8.8.8.8: seq=1 ttl=37 time=15.320 ms
64 bytes from 8.8.8.8: seq=2 ttl=37 time=11.111 ms
...
kubectl delete -f pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo
spec:
containers:
- name:testpod
image: alpine:3.5
command: ["ping","8.8.8.8"]
这描述了具有单个容器的容器,将简单的ping隔离到8.8.8.8。
kubectl apply -f pod.yaml
kubectl get pods
您应该看到类似以下内容:
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 0 4s
kubectl logs demo
您应该看到一个健康的ping过程的输出:
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=37 time=21.393 ms
64 bytes from 8.8.8.8: seq=1 ttl=37 time=15.320 ms
64 bytes from 8.8.8.8: seq=2 ttl=37 time=11.111 ms
...
kubectl delete -f pod.yaml
Docker Desktop主要在Docker Engine上运行,它具有运行Swarm所需的一切内置功能。请按照适用于您的操作系统的设置和验证说明进行操作:
docker swarm init
如果一切顺利的话,你应该会看到类似以下内容的消息:
Swarm initialized: current node (tjjggogqpnpj2phbfbz8jd5oq) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3e0hh0jd5t4yjg209f4g5qpowbsczfahv2dea9a1ay2l8787cf-2h4ly330d0j917ocvzw30j5x9 192.168.65.3:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
docker service create --name demo alpine:3.5 ping 8.8.8.8
docker service ps demo
您应该看到类似以下内容:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
463j2s3y4b5o demo.1 alpine:3.5 docker-desktop Running Running 8 seconds ago
docker service logs demo
您应该看到一个健康的ping过程的输出:
demo.1.463j2s3y4b5o@docker-desktop | PING 8.8.8.8 (8.8.8.8): 56 data bytes
demo.1.463j2s3y4b5o@docker-desktop | 64 bytes from 8.8.8.8: seq=0 ttl=37 time=13.005 ms
demo.1.463j2s3y4b5o@docker-desktop | 64 bytes from 8.8.8.8: seq=1 ttl=37 time=13.847 ms
demo.1.463j2s3y4b5o@docker-desktop | 64 bytes from 8.8.8.8: seq=2 ttl=37 time=41.296 ms
...
docker service rm demo
docker swarm init
如果一切顺利的话,你应该会看到类似以下内容的消息:
Swarm initialized: current node (tjjggogqpnpj2phbfbz8jd5oq) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3e0hh0jd5t4yjg209f4g5qpowbsczfahv2dea9a1ay2l8787cf-2h4ly330d0j917ocvzw30j5x9 192.168.65.3:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
docker service create --name demo alpine:3.5 ping 8.8.8.8
docker service ps demo
您应该看到类似以下内容:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
463j2s3y4b5o demo.1 alpine:3.5 docker-desktop Running Running 8 seconds ago
docker service logs demo
您应该看到一个健康的ping过程的输出:
demo.1.463j2s3y4b5o@docker-desktop | PING 8.8.8.8 (8.8.8.8): 56 data bytes
demo.1.463j2s3y4b5o@docker-desktop | 64 bytes from 8.8.8.8: seq=0 ttl=37 time=13.005 ms
demo.1.463j2s3y4b5o@docker-desktop | 64 bytes from 8.8.8.8: seq=1 ttl=37 time=13.847 ms
demo.1.463j2s3y4b5o@docker-desktop | 64 bytes from 8.8.8.8: seq=2 ttl=37 time=41.296 ms
...
docker service rm demo
至此,您已经在开发机器上安装了Docker Desktop,并确认可以在Kuberentes和Swarm中运行简单的容器化工作负载。 在下一节中,我们将开始开发我们的第一个容器化应用程序。
现在,借助Docker Desktop,我们已经在我们的开发环境中设置了编排器,我们可以开始开发容器化的应用程序。通常,开发工作流程如下所示:
在本教程的此阶段,我们将重点放在此工作流程的第1步:将基于镜像创建容器。请记住,Docker镜像捕获我们的容器化进程将在其中运行的私有文件系统;我们需要创建一个镜像,其中包含我们的应用程序需要运行的内容。
一旦学习了如何构建镜像,容器化的开发环境就比传统的开发环境更容易建立,我们将在下面讨论。这是因为容器化的开发环境将隔离您的应用程序在Docker镜像中所需的所有依赖关系;除了在您的开发机器上安装Docker外,无需安装其他任何工具。这样,您可以轻松开发用于不同堆栈的应用程序,而无需在开发计算机上进行任何更改。
git clone -b v1 https://github.com/docker-training/node-bulletin-board
cd node-bulletin-board/bulletin-board-app
这是一个简单的公告板应用程序,用node.js编写。 在此示例中,假设您编写了此应用,现在正尝试将其容器化。
FROM node:6.11.5
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm","start"]
编写Dockerfile是容器化应用程序的第一步。您可以将这些Dockerfile command
视为有关如何构建镜像的逐步指南。此步骤采取以下步骤:
/usr/src/app
中执行(而不是主机(本机计算机)的文件系统中)。/usr/src/app/package.json
)npm install
(它将读取package.json以确定应用程序的node依赖,然后安装它们)您可以看到,这些步骤与在主机上设置和安装应用程序所采取的步骤几乎相同-但是将它们收缴捕获为一个Dockerfile可以使我们在可移植的隔离Docker镜像中执行相同的操作。
上面的步骤构建了镜像的文件系统,但是Dockerfile中还有一行。 CMD指令是我们在镜像中指定一些元数据的第一个示例,该元数据描述了如何基于该镜像运行容器。在本例中,就是说该镜像需要支持的容器化过程是npm start
。
npm start
编译运行app ,是在运行容器之后执行上面您看到的是组织一个简单的Dockerfile的好方法。始终以FROM命令开头,然后按照步骤构建您的私有文件系统,并以任何元数据规范作为结束。 Dockerfile指令比上面我们看到的要多。有关完整列表,请参阅Dockerfile参考。
现在我们有了一些源代码和一个Dockerfile,现在该构建我们的第一个映像,并确保从其启动的容器可以按预期工作。
Windows用户:此示例使用Linux容器。 右键单击系统任务栏中的Docker图标,然后单击“切换到Linux容器…”,以确保您的环境正在运行Linux容器。 不用担心-您将在本教程中学到的所有内容都与Windows容器完全相同。
node-bulletin-board/bulletin-board-app
中,并构建公告板镜像像:# -t tagname 编译镜像并为镜像打个tag
docker image build -t bulletinboard:1.0 .
您会看到Docker逐步完成Dockerfile中的每条指令,并逐步构建镜像。 如果成功,则构建过程应以一条消息“Successfully tagged bulletinboard:1.0”结束。
Windows用户:您可能会在此步骤收到一条标题为“安全警告”的消息,其中指出了为添加到图像中的文件设置的读取,写入和执行权限; 在此示例中,我们不处理任何敏感信息,因此在此示例中,请不要理会此警告。
docker run -p 8000:8080 -d --name bb bulletinboard:1.0
#或者
docker run --publish 8000:8080 --detach --name bb bulletinboard:1.0
我们在这里使用了几个常见的标志:
另请注意,我们没有指定我们要运行容器的进程。 我们不必这样做,因为在构建Dockerfile时使用了CMD指令; 因此,Docker知道在启动时会自动在容器内运行npm start
命令。
在浏览器中的localhost:8000上访问您的应用程序。 您应该看到公告板应用程序已启动并正在运行。 在这一步,我们通常会竭尽所能,以确保我们的容器按预期的方式工作; 例如,现在是运行单元测试的时候了。
对公告板容器正常工作感到满意后,将其删除:
docker container rm --force bb
至此,我们已经对应用程序进行了简单的容器化,并确认我们的应用程序已在其容器中成功运行。 下一步将是编写Kubernetes yaml,以描述如何在Kubernetes上运行和管理这些容器(我们将在本教程的第3部分中进行研究),或者编写堆栈文件以使我们能够在Docker Swarm上进行相同的操作, 我们将在第4部分中进行讨论。
既然我们已经证明了应用程序的各个组件都是作为独立容器运行的,那么现在该安排它们由Kubernetes这样的编排器来管理了。 Kubernetes提供了许多工具来扩展,联网,保护和维护您的容器化应用程序,这超出了容器本身的能力。
为了验证我们的容器化应用程序是否可以在Kubernetes上正常运行,我们将在开发机器上使用Docker Desktop内置的Kubernetes环境在我们的应用程序上部署我们的应用程序,然后再将其移交给生产环境中的完整Kubernetes集群。 Docker Desktop创建的Kubernetes环境具有完整的功能,这意味着它具有您的应用程序将在真实集群上享受的所有Kubernetes功能,可从开发机器的便利性进行访问。
Kubernetes中的所有容器都规定为Pod,这是一组共享资源的共享容器。此外,在实际的应用程序中,我们几乎从不创建单个Pods。取而代之的是,我们的大多数工作负载都按部署计划,这些部署是Kubernetes自动维护的可扩展Pod组。最后,所有Kubernetes对象都可以并且应该在称为Kubernetes YAML文件的清单中进行描述。这些YAML文件描述了Kubernetes应用程序的所有组件和配置,可用于在任何Kubernetes环境中轻松创建和销毁您的应用程序。
apiVersion: apps/v1
kind: Deployment
metadata:
name: bb-demo
namespace: default
spec:
replicas: 1
selector:
matchLabels:
bb: web
template:
metadata:
labels:
bb: web
spec:
containers:
- name: bb-site
image: bulletinboard:1.0
---
apiVersion: v1
kind: Service
metadata:
name: bb-entrypoint
namespace: default
spec:
type: NodePort
selector:
bb: web
ports:
- port: 8080
targetPort: 8080
nodePort: 30001
在此Kubernetes YAML文件中,我们有两个对象,中间用- - -分隔:
还要注意,虽然Kubernetes YAML乍看起来可能很长很复杂,但几乎总是遵循相同的模式:
在terminal中,导航到创建bb.yaml的位置,然后将应用程序部署到Kubernetes:
kubectl apply -f bb.yaml
你应该看到的输出类似于以下消息,表明已成功创建您的Kubernetes对象:
deployment.apps/bb-demo created
service/bb-entrypoint created
kubectl get deployments
如果一切顺利,则您的部署应列出如下:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
bb-demo 1 1 1 1 48s
这表明您在YAML中要求的所有Pod都已启动并正在运行。 对服务进行相同的检查:
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bb-entrypoint NodePort 10.106.145.116 <none> 8080:30001/TCP 53s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 138d
除了默认的kubernetes服务,我们还看到了bb-entrypoint服务,该服务接受端口30001/TCP上的流量。
打开浏览器,访问位于localhost:30001的公告板; 您应该看到您的公告板,就像在本教程的上一步中将其作为独立容器运行时一样。
一旦满意,请删除您的应用程序:
kubectl delete -f bb.yaml
至此,我们已经成功地使用Docker Desktop将我们的应用程序部署到我们开发机器上功能齐全的Kubernetes环境中。 我们还没有对Kubernetes进行很多工作,但是现在已经打开了大门:您可以在自己的机器上开始向应用程序添加其他组件,并利用Kubernetes的所有功能和强大功能。
除了部署到Kubernetes,我们还将应用程序描述为Kubernetes YAML文件。 这个简单的文本文件包含在运行状态下创建应用程序所需的一切; 我们可以将其加入版本控制并与同事共享,从而使我们可以轻松地将应用程序分发到其他集群(例如可能在我们开发环境之后的测试和生产集群)。
现在,我们已经演示了应用程序的各个组件可以作为独立容器运行,并展示了如何使用Kubernetes进行部署,让我们看看如何安排它们由Docker Swarm管理。 Swarm提供了许多工具,可以扩展,联网,保护和维护您的容器化应用程序,而容器本身无法提供这些工具。
为了验证我们的容器化应用程序在Swarm上能否正常运行,我们将在开发机器上使用Docker Desktop内置的Swarm环境来部署我们的应用程序,然后再将其移交给生产环境中的完整Swarm集群。 Docker Desktop创建的Swarm环境具有完整的功能,这意味着它具有您的应用程序将在真正的群集上享受的所有Swarm功能,可通过开发机器的便利性进行访问。
Swarm从来不会像本教程的上一步那样创建单个容器。而是将所有Swarm工作负载安排为服务,这些服务是可伸缩的容器组,具有由Swarm自动维护的附加网络功能。此外,所有Swarm对象都可以并且应该在称为 stack文件的清单中进行描述。这些YAML文件描述了Swarm应用程序的所有组件和配置,可用于在任何Swarm环境中轻松创建和销毁您的应用程序。
version: '3.7'
services:
bb-app:
image: bulletinboard:1.0
ports:
- "8000:8080"
在这个Swarm YAML文件中,我们只有一个对象:服务,描述一组可伸缩的相同容器。 在这种情况下,您只会得到一个容器(默认容器),并且该容器将基于本教程第2步中的bulletinboard:1.0镜像。 我们还要求Swarm将所有到达开发计算机上8000端口的流量转发到公告板容器内的8080端口。
Kubernetes服务和Swarm服务有很大的不同! 尽管名称相似,但两个编排器的“service”一词含义却截然不同。 在Swarm中,service同时提供调度和联网功能,创建容器并提供用于将流量路由到它们的工具。 在Kubernetes中,调度和联网 分别处理:Deployment(或其他控制器)将容器的调度,作为Pod处理,而Service仅负责将网络功能添加到这些Pod。
docker stack deploy -c bb-stack.yaml demo
如果一切顺利,Swarm将报告创建所有stack对象而不会产生任何投诉:
Creating network demo_default
Creating service demo_bb-app
请注意,除服务外,Swarm默认还会创建一个Docker网络,以隔离作为你的stack一部分,部署的容器。
docker service ls
如果一切顺利,您的服务将1对1的报告其创建的副本:
ID NAME MODE REPLICAS IMAGE PORTS
il7elwunymbs demo_bb-app replicated 1/1 bulletinboard:1.0 *:8000->8080/tcp
这表示您在服务中要求的1对1的容器,已启动并正在运行。 此外,我们看到开发计算机上的端口8000已转发到公告板容器中的端口8080。
打开浏览器,访问位于localhost:8000的公告板; 您应该看到您的公告板,就像在本教程的步骤2中将其作为独立容器运行时一样。
完成以后,删除你的应用
docker stack rm edmo
至此,我们已经成功地使用Docker Desktop将我们的应用程序部署到开发机器上的功能齐全的Swarm环境中。 我们尚未对Swarm做很多事情,但是现在已经打开了大门:您可以在自己的计算机上开始向应用程序添加其他组件,并利用Swarm的所有功能和强大功能。
除了部署到Swarm之外,我们还将应用程序描述为stack文件。 这个简单的文本文件包含在运行状态下创建应用程序所需的一切; 我们可以将其检入版本控制并与同事共享,从而使我们可以轻松地将应用程序分发到其他集群(例如可能在我们开发环境之后的测试和生产集群)。
已完成在第2部分中通过容器化应用程序工作。
至此,您已经在第2部分中构建了一个容器化的应用程序,并有可能在Docker第3部分中的Kubernetes或第4部分中的Swarm上运行它,这一切都归功于Docker Desktop。开发容器化应用程序的最后一步是在Docker Hub等registry上共享您的镜像,以便可以轻松下载它们并在任何目标群集上运行它们。
如果您还没有Docker ID,请按照以下步骤进行设置;这将允许您在Docker Hub上共享镜像。
您可以通过在命令行中输入docker login来执行相同的操作。
至此,您已经设置了Docker Hub帐户并将其连接到Docker桌面。 现在,让我们进行第一个存储库,并在那里共享公告栏应用程序。
点击菜单栏中的Docker图标,然后导航至repositorries->Create…。您将转到Docker Hub页面来创建新的repository。 填写repository名称作为bulletinboard. 现在暂时保留所有其他选项,然后单击底部的创建。
3. 现在,我们准备在Docker Hub上共享镜像,但是我们首先要做的是:必须正确命名镜像的名称才能在Docker Hub上共享。 具体来说,镜像必须像 / :这样命名。 我们可以像这样重新标记我们的bulletinboard:1.0镜像(当然,请用您的Docker ID替换gordon):
docker tag bulletinboard:1.0 gengqianyu/bulletinboard:1.0
docker image push gengqianyu/bulletinboard:1.0
在Docker Hub中访问您的repository,您将在此处看到新镜像。 请记住,默认情况下,Docker Hub repository 是公共的。
推送有困难吗? 请记住,您必须通过Docker Desktop或命令行登录Docker Hub,并且还必须按照上述步骤正确命名映像。 如果该推送似乎有效,但您在Docker Hub中看不到它,请在几分钟后刷新浏览器,然后再次检查。
现在,您的镜像已在Docker Hub上可用,您将可以在任何地方运行它;如果您尝试在尚未安装的新群集上使用它,则Docker将自动尝试从Docker Hub下载。通过以这种方式移动镜像,我们不再需要在要运行软件的机器上安装Docker和Orchestrator以外的任何依赖项;容器化应用程序的依赖关系已完全封装并隔离在我们的镜像中,我们可以按上述方式通过Docker Hub进行共享。
需要记住的另一件事:目前,我们仅将您的镜像推送到Docker Hub;您的Dockerfile,Kube YAML和stack文件呢?关键的最佳实践是将它们保留在版本控制中,或者与应用程序的源代码一起保留,并在Docker Hub存储库描述中添加链接或注释,以指示可以在何处找到这些文件,不仅保存镜像的记录是构建的,但它是作为完整的应用程序运行的。