在本教程中,我们将了解容器化,Docker及其组件的历史,以及如何在日常工作中开始使用它。 但是,在我们过于深入地学习本教程之前,让我们看一下Docker是什么,以便我们对将要使用的Docker有所了解。
1.简介
Docker是一个用于构建,交付和运行分布式应用程序的开放平台。 它为程序员,开发团队和运营工程师提供了他们所需的通用工具箱,以利用现代应用程序的分布式和联网性质。
如上面Docker的正式定义所述,它可以帮助开发人员或操作工程师自动化应用程序所需的基础架构环境。
假设您有一个用Node.js编写的应用程序,该应用程序将Express用于RESTful服务,将MongoDB用于数据持久性。 让我们变得更加复杂,并在Node.js实例前面添加多个Node.js和Nginx负载均衡器实例。
如果我将安装步骤记录在一个文本文件中,然后让某人为我安装整个环境,这会更好吗? Docker帮助您非常轻松地将架构的所有组件(Node.js实例,Nginx Web服务器,MongoDB数据库等)容器化。
但是,什么是集装箱化? 让我们看一下容器化技术的历史。
2.集装箱化的历史
我记得的第一个容器化项目是OpenVZ ,它是2005年首次发布的基于容器的Linux虚拟化。OpenVZ允许您创建多个隔离的安全Linux容器,以便在同一台物理服务器上运行它们,而应用程序之间没有任何冲突。 。
同时,另一个FreeBSD项目出现了,叫做Jails 。 这使您可以使用chroot将应用程序和服务放入一个Jail(我们可以称其为容器)。
还有其他类似Solaris Containers的项目,但是,尽管上述所有容器化项目都比Docker早八年,但Docker为什么会流行起来? 继续阅读以提升您的Docker知识。
3. Docker如何工作?
在解释Docker的工作方式之前,让我解释一下容器的工作方式。 容器与操作系统级虚拟化有关,它使我们可以创建多个隔离的用户空间,而不仅仅是一个。 通过使用chroot
进行隔离。
容器和虚拟机之间的主要区别如下。 使用VM创建多个虚拟机时,每个来宾都将复制操作系统和虚拟化硬件。 但是,如果创建多个容器,则只会从头开始创建与操作系统发行版相关的文件夹,而与Linux内核相关的部分将在容器之间共享。 您可以看下面的图片,以直观的方式查看区别。
虚拟机
![VM工作架构](https://cms-assets.tutsplus.com/uploads/users/487/posts/24770/image/hgd-1.png)
码头工人
![集装箱工作架构](https://i-blog.csdnimg.cn/blog_migrate/f99e41c38d9bb3171ef51aeb01b99a6a.png)
您也可以在模式中看到,如果使用VM创建Ubuntu和Mint guest虚拟机,则即使它们使用相同的Linux内核,它们的Guest OS也将被复制。 实际上,分发意味着将bins和libs文件夹区分开,并且Linux内核是相同的。
如果您看一下上面的第二张图片,您将看到所有操作系统级别的体系结构在各个容器之间共享,并且只为不同的容器从头开始创建了bins和libs 。 Docker Engine具有命名空间, cgroups
和SELinux,可帮助您协调容器。 如果您需要有关Docker Engine的更多信息,请访问Docker网站 。
4. Docker组件
在继续解释组件之前,您可以将Docker安装到您的计算机上 。 它具有非常基本的安装步骤。
Docker主要包含两个组件:Docker Engine和Docker Hub。 如前所述,Docker Engine用于编排容器,而Docker Hub是用于管理和共享应用程序堆栈的SaaS服务。 例如,如果要在Docker上使用Redis,则可以通过执行以下命令将其拉到本地计算机上:
docker pull redis
这将获取容器映像的所有层,并准备在您的环境中运行。 您可以查看Docker Hub上的许多存储库。
码头工人也有称为AUFS一个特殊的文件系统(先进适用的一个多层次的ünification˚FILE 变体系)。 使用此系统,每个提交更改都保持在层中,例如版本控制。 如果您对Docker映像进行更改,它将被保存为其他提交,并且不会在构建操作中完全重建。 所有其他层均已构建。
此外,将存储库拉到本地计算机时,您将看到提取操作是逐层进行的。 假设您进行了更改并测试了新容器,但是失败了。 没问题,您可以像往常一样在Git中回滚更改并重建。
5.快速入门
假设您的计算机上已经安装了Docker,我们可以开始使用一些非常酷的Docker命令。
docker pull ubuntu
docker run -it ubuntu bash
您可能会猜到,以上命令将从Docker Hub获取ubuntu映像,然后运行它,然后执行bash命令。
执行上述命令后,您将看到自己在容器中。 您现在位于Ubuntu Shell中,可以自由执行* nix命令。 您可以创建内容,删除内容,查看流程等。
但是,请小心,因为无论何时退出容器,您的数据都会丢失。 为什么? 因为您需要将容器设计为不可变的。
首先设计将包含哪些软件包,将哪些应用程序克隆到容器中,等等,然后运行您的容器。 每当发生任何故障时,您都需要能够更改配置并再次运行。 切勿在容器中保持状态。
跑
为了运行容器,可以使用以下格式。
docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
Docker中有许多用于运行操作的参数。 您可以参考文档中的所有选项,但我将为您提供一些实际使用示例。
docker run -d redis
此命令将以分离模式运行Redis映像。 这意味着所有I / O将通过网络或共享连接来完成。 您可以假定它以守护程序模式运行。 我们在这里说过redis
,但是您也可以使用以下命令来指定图像作者和标签。
docker run -d huseyinbabal/mongodb:1.0
我们正在运行一个属于huseyinbabal
的mongodb
映像,具有特定版本1.0
。
您也可以像这样交互式地运行图像:
docker run -it huseyinbabal/ubuntu:1.2 bash
当您运行上述命令时,它将运行ubuntu 1.2
,然后执行bash
命令以将提示放入容器内的终端。
建立
我们已经运行了从Docker Hub存储库中提取的映像。 如何建立自己的形象? 我们可以使用Docker build命令来做到这一点,但是我们需要指定一个Dockerfile
以使Docker运行Dockerfile中定义的每个语句。
FROM ubuntu
MAINTAINER Huseyin BABAL
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
RUN echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" | tee -a /etc/apt/sources.list.d/10gen.list
RUN apt-get update
RUN apt-get -y install apt-utils
RUN apt-get -y install mongodb-10gen
RUN echo "some configs" >> /etc/mongodb.conf
CMD ["/usr/bin/mongod", "--config", "/etc/mongodb.conf"]
这是一个非常简单的Dockerfile定义,将帮助我们构建映像。 在此Dockerfile定义中,首先我们要说的是,我们将从ubuntu映像继承所有属性。 该图像将首先从本地服务器获取。 如果找不到,将从Docker Hub获取。
在第二行,我们定义图像的作者或维护者。 在以下文件中,我们仅使用RUN命令运行一些* nix命令,以安装基本软件包和与MongoDB相关的软件包。 为了启动MongoDB,我们正在编写mongodb.conf
,最后一步是使用CMD
运行命令。
为了运行我们的映像,我们应该使用此Dockerfile来构建映像。 您可以使用以下内容来构建图像。
docker build -t huseyinbabal/mongodb:1.0 .
简而言之,这将构建一个带有huseyinbabal/mongodb:1.0
标签的映像,并将在当前文件夹中使用Dockerfile(请参阅命令末尾的点)。 为了测试它是否被创建,您可以使用以下命令。
docker images
这将列出计算机上存在的所有图像,如下所示。
![码头工人图像](https://i-blog.csdnimg.cn/blog_migrate/1ee464dc698aa7bc8ff708003bf0f326.png)
如果要运行构建的映像,则可以简单地运行:
docker run -d huseyinbabal/mongodb:1.0
可是等等! 这是守护程序节点。 那么,如何输入此容器? 这很简单。 首先,使用以下命令获取mongodb容器名称的名称。
docker ps
您将看到类似以下的输出。
![码头工人ps](https://cms-assets.tutsplus.com/uploads/users/487/posts/24770/image/hgd-4.png)
您可以在“名称”列中看到该名称。 现在是时候使用以下命令进入容器了。
docker exec -i -t <container_name> bash
您可以看到此容器中正在运行的进程。
共享文件夹
如前所述,如果关闭正在运行的容器,则与该容器有关的所有数据都将丢失。 这在Docker世界中很正常。
例如,在我们的容器中,MongoDB将所有数据写入mongodb.conf中指定的路径中。 该文件夹位于容器中,如果关闭容器,所有数据将丢失。 如果将数据保留在与Docker运行的主机共享的文件夹中,则可以在run
命令中使用-v
选项。 例如:
docker run -d -v /host/mongo_data_path:/container/mongo_data_path huseyinbabal/mongodb:1.0
这会将host/mongo_db_path
/ host/mongo_db_path
映射到container/mongo_data_path
中的/ container/mongo_data_path
。 每当mongo将数据写入容器内部的路径时,它将在主机内部自动访问。 即使关闭容器,数据也将保留在主机内部的路径中。
端口暴露
假设MongoDB在容器内运行。 您可以在端口27017的容器外部公开MongoDB端口,并且可以使用以下命令从具有端口5000的容器外部访问。
docker run -d -P 5000:27017 -v /host/mongo_data_path:/container/mongo_data_path huseyinbabal/mongodb:1.0
因此,您可以使用端口5000从外部连接到容器内部的MongoDB。
集装箱检查
假设您需要指定容器的网络信息。 您可以使用docker inspect <container_id>
命令获取详细信息。 此命令将打印有关容器的大量元数据。 <container_id>
是docker ps
输出中的CONTAINER ID
中存在的部分。 检查的输出将为JSON格式。 为了获得容器的IP地址,您可以使用:
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container_id>
上面的命令是您执行Docker时的基本命令。 如果您需要了解更多有关Docker命令的信息,请参考文档 。
6.技巧和窍门
集装箱单一责任
最佳做法是对每个容器仅授予一个责任。 我的意思是,您不应该在一个容器中安装MongoDB和Spring Boot应用程序以在一个容器中为DB和Application层提供服务。 取而代之的是,您可以将一个应用程序放在一个容器中。 每个应用程序实例,数据库成员,消息队列等应仅声明一个容器。
假设您将应用程序和数据库层放在一个容器中。 测量应用程序或数据库的性能或诊断将非常困难。 同样,如果要扩展应用程序,则将无法扩展该容器,因为该容器中还安装了数据库应用程序。
不变的容器
运行容器时,切勿将其放入该容器中以进行更新或删除。 使用Docker的主要原因是将更改保留在历史上。 如果要更改某些内容,请更改Dockerfile,构建映像,然后运行容器。 即使您手动更改了容器内的某些内容,如果重新运行该容器,该内容也会被删除。
Dockerfile层
通常,您可能希望将每个命令写在下面的不同行上。
FROM ubuntu
MAINTAINER Huseyin BABAL
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y php5
RUN apt-get install -y nginx
CMD ["nginx", "g", "daemon off;"]
EXPOSE 80
这意味着每行一层。 这不是建议的构建Dockerfile的方法。 您可以为每组作业使用反斜杠(\)分隔命令,如下所示:
FROM ubuntu:15.04
MAINTAINER Huseyin BABAL
RUN apt-get update \
-y build-essential
-y php5 \
-y nginx=1.7.9 \
apt-get clean
CMD ["nginx", "g", "daemon off;"]
EXPOSE 80
在上面的Dockerfile中,我们计划将所需的软件包安装在一行上,并执行了clean
操作以使环境变得干净。 这样,我们没有为每个命令创建单独的层。
集装箱日志
构建和运行容器是非常容易的事情。 两个月后,您可能会得到50个用于应用程序架构的容器! 如果您的容器中发生任何错误,将很难找到问题的根本原因。
解决此问题的简单方法是将容器活动记录在中央日志系统中。 例如,将您的标准输出日志重定向到每个容器内的日志文件。 代理可以将这些日志内容流式传输到中央日志管理系统,例如ELK或Splunk。 如果您在日志中发送特定于容器的数据,例如容器ID,则在日志管理仪表板上过滤错误非常容易。
您可能需要监视容器本身。 这次,您可以看看Google cadvisor 。 这使您可以通过REST服务监视容器。 例如,为了查看容器信息,您可以向http://host_name
/api/v1.0/containers/<absolute container name>
发出GET请求。
标准化
如果将标准过程应用于容器生命周期,则控制整个体系结构将非常容易。 例如,您可以创建一个基本容器来继承其他容器中的某些操作。 另一方面,您可以将标准位置用于配置文件,日志文件和源文件。 请注意为每个容器使用单独的Dockerfile。 最后,将版本控制应用于所有容器以分离功能,并根据需要使用不同的版本。
安全
对于容器,安全性是一个非常重要的主题。 始终以非特权模式运行容器。 我建议您使用Apparmor来保护您的容器免受外部线程的影响,甚至是零日攻击。 我还建议SELinux用于您的容器,以根据您的需求应用访问控制安全策略。 另外,请紧跟容器中使用的图像更新,以将最新的补丁程序应用到容器。 执行此操作时,不要忘记将图像固定到稳定版本。
7.模数
Modulus是一个完全受支持的企业部署和编排平台。 他们首先从LXC之上的Node.js为重点的PaaS开始,然后他们决定切换到Docker,这使他们可以支持更多与Node.js不同的语言,例如PHP,Java,Python和Static项目。
我这里所说的支持语言的意思是,您可以使用具有预定义属性的单个命令将以上述语言编写的应用程序部署到Modulus。 假设您要将Node.js应用程序部署到Modulus,唯一要做的就是在项目根文件夹中执行modulus deploy
。 模量由以下部分组成。
模量CLI
Modulus CLI用于从命令行对您的应用程序进行部署操作,可以使用npm install -g modulus
进行简单安装。 您可以使用Modulus CLI创建项目,部署项目,流日志以及执行一些与数据库相关的操作。 另外,您可以通过管理面板上载来部署项目。
部署方式
您可以通过几个简单的步骤来创建和部署应用程序。 您可以选择语言,伺服大小和位置。 然后准备部署您的项目。
![模数创建项目](https://i-blog.csdnimg.cn/blog_migrate/18b2b77b9c03ace7556e199db783f972.png)
或者,您可以在命令行上创建一个modulus project create <project_name>
,然后modulus deploy
。
数据库
您可能需要在应用程序中存储一些数据。 Modulus还允许您将数据库添加到您的应用程序。 MongoDB在后台使用。 您可以在仪表板内创建数据库,也可以在命令行上创建数据库。 您可以在下面看到数据库屏幕。
![模量数据库](https://cms-assets.tutsplus.com/uploads/users/487/posts/24770/image/modulus_db.png)
您可以在详细信息屏幕上获取数据库URL并在您的应用程序中使用它。
日志
您可以在命令行中使用modulus logs tail
尾部添加应用程序日志,也可以如下在仪表板上流式传输日志。
![应用程序日志](https://i-blog.csdnimg.cn/blog_migrate/da8d51028e5e83de8ed8b3ad25be9c4a.png)
单击“ STREAM”按钮时,您可以实时查看日志。
这些是模量的主要组成部分。 您可以在Modulus仪表板上查看其他组件,例如Metrics , Auto-Scaling , Addons , Notifications和Administration 。
8.结论
我们已经讨论了容器并给出了简短的历史。 与VM相比,Docker具有许多替代方案来管理您的应用程序基础架构。
如果您在架构上使用Docker,则需要注意一些概念,例如单一职责,不可变服务器,安全性,应用程序和容器监视。
当您的系统变大时,将非常易于控制。 Modulus是将Docker用于其PaaS系统的公司之一。 通过使用Docker的功能,Modulus设计了一个出色的系统,可以帮助人们非常轻松地部署用Node.js,PHP,Java和Python编写的应用程序。
翻译自: https://code.tutsplus.com/tutorials/the-hitchhikers-guide-to-docker-and-modulus--cms-24770