关于Docker的内容

假设

我将写下我学到的有关Docker的知识。

這個問題

关于Docker的事项

卓越之处

・ローカル環境でDockerのセットアップが済んでいれば、数行の構成ファイルとコマンドを1つ叩くだけで検証環境が作成される。
・アプリケーションやミドルウェアがすでにセットアップされている状態の仮想環境(Dockerコンテナ)が手早く準備できる。
・Dockerコンテナは仮想化ソフトウェアと比較してより少ないオーバーヘッドで動作する。
・Dockerは開発環境の準備だけでなく、その後の本番環境への展開や、アプリケーションプラットフォームとして機能する。

与旧款型号的不同

【若是旧来模式】

在开发Web应用程序时,在本地环境中搭建像Apache或Nginx这样的Web服务器。
也就是说,在虚拟环境中设置与生产环境相同的操作系统,并参考文档使用包管理器逐步安装所需的组件等来构建环境。

【在Docker的情况下】

将在本地Docker环境中运行的容器部署到另一台服务器上的Docker环境中。
或者是将运行在服务器的Docker环境中的容器带到本地。
换句话说,几乎同时复制开发环境和生产环境。

Docker的不擅长之处。

Dockerコンテナの内部はLinux系OSのような構成をしているものが多くを占める。
コンテナはOSとして振る舞いを完全に再現しているわけではない。
より厳格にLinux系OSとして振る舞う仮想環境を構築したい場合は、従来通りVMWareやVirtualBoxといった仮想化ソフトウェアを利用すべき。
またFreeBSDなど非Linuxの環境を動作させたい場合とは目的が違うため、本来Dockerはこれからと競合する存在ではない。

Docker基础概念

Docker利用了容器化虚拟化技术。
容器化虚拟化技术在Docker之前就已经存在。
Docker出现之前,LXC(Linux Containers)很有名。
Docker最初阶段使用了LXC,现在则使用了名为runC的运行时来实现容器化虚拟化。

コンテナ型仮想化技術では仮想化ソフトウェアなしにOSのリソースを隔離し、仮想OSにする。
この仮想OSをコンテナと呼ぶ。
コンテナを作り出すためのオーバーヘッドは、他の仮想化ソフトウェアと比較して少ない。
高速に起動・終了でき、必要なマシンリソースも少なくて済む。
OS上にインストールした仮想化ソフトウェアを利用し、ハードウェアを演算により再現しゲストOSを作り出す仕組みはホストOS型の仮想化と呼ぶ。コンテナ型仮想化に比べると仕組み上オーバーヘッドが大きくなる。

专注于应用程序的Docker

LXCはホスト型仮想化技術よりパフォーマンス面で有利なため、システムコンテナとしての用途で一定の地位を確立した。
しかし、LXCでは複製したアプリケーションを別のLXCホストで実行しようとしても、LXCの設定に差異があれば期待した動作が得られないなどの問題がある。
アプリケーションのデプロイ・運用の観点では、機能が不足している。
・ホストに左右されない実行環境(Dockerengineによる実行環境の標準化)
・DSL(Dockerfile)によるコンテナ構成やアプリケーション配置定義
・イメージのバージョン管理
・レイヤ構造を持つイメージフォーマット(差分ビルドが可能)
・Dockerレジストリ(イメージの保管サーバのようなもの)
・プログラマブルな各種API

DockerではDockerfileによりコンテナの情報をコードで管理できるようになった。
このコードをベースに取得や配布の支援も行われていて、再現性が保ちやすいのが特徴。
旧来のLXCとは異なり、Dockerベースでデプロイのスタイルが確立・普及する。
Docker以前はアプリケーションをホストOS、またはゲストOSにデプロイするスタイルが主流。
この方式だと、アプリケーションは実行環境(OS)に強く依存している。
対して、Dockerはコンテナにアプリケーションと実行環境(OS)を同梱してデプロイするスタイルを採用している。
実行環境ごと配布することで、依存問題の困難さを解決している。

Dockerfile的中文意思是什么?

Dockerがどんなイメージを作成・実行するか定義する。
Dockerfileやアプリケーションの実行ファイルからDockerコンテナの元となるイメージを作ることを、Dockerイメージをビルドするという。
Dockerfileはベース(コンテナの雛形)となるDockerイメージ(OS)をFROMで定義できる。
COPYでは作成したhelloworldファイルをホスト側から、Dockerコンテナ内の/usr/local/binにコピーしている。
RUNはDockerコンテナ内で任意のコマンドを実行できる仕組み。ここではhelloworldスクリプトに実行権限を与えたいる。
ここまでがDockerビルド時に実行され、新たなDockerイメージとして生成される。
CMDは出来上がったイメージをDockerコンテナとして実行する前に行われるコマンドを定義する。
ここは事実上、アプリケーションを実行するコマンドを指定することになる。

FROM ubuntu:16.04

COPY helloworld /usr/local/bin
RUN chmod +x /usr/local/bin/helloworld

CMD["helloworld"]

在含有Dockerfile的文件夹中执行docker image build命令,构建并运行Docker镜像。

一但建置完成,使用docker container run命令執行Docker容器是基本流程。
這樣,將應用程式所需的文件與Docker映像(作業系統)捆綁在一起,並作為容器來執行,這是Docker的基本風格。
本例中,將Shell腳本捆綁到ubuntu上,以作為容器來執行。

在实际开发中,部署在Docker容器中的应用程序主要是像Web应用程序和API应用程序这样需要持续运行的进程。例如,考虑一个基于Node.js的Web应用程序,该应用程序会一直保持运行状态。与本次例子相比,容器的构建也变得更加复杂。使用基于所依赖的Node.js版本的映像,并在容器内使用npm来进行模块安装和构建过程,从而完成映像的制作。在执行方面与执行echo命令的方式相同。制作完成的映像只要Docker正在运行,就可以在任何主机环境中执行,无需在主机上安装Node.js或npm。

通过使用Docker,可以快速准备需要的应用程序作为本地开发环境,并且可以在各种平台上部署,而不受平台的限制。
通过Docker容器获取固定的执行环境,可以将环境问题最小化。
此外,还可以在Web应用程序的前端上部署像Apache或nginx这样的Web服务器,而无需复杂的步骤即可在容器中进行配置。
系统包括中间件在内的配置管理也可以通过设置文件来定义。

你是否曾经因为环境差异问题而陷入这种困境而指定应用程序开发?

「Bのサーバにも同じアプリケーションをデプロイしたんですが、Aのサーバとでアプリケーションの挙動が違うんですよね・・・」
「うーん、どのサーバにも同じアーカイブを配布しているはずですが・・・」
「サーバの設定や、インストールしているライブラリに差異があるかもしれないよ?」
「あー、Bのサーバにインストールされているライブラリが古かったようです。アップデートしますね!」
「やはり・・・、各サーバの状態を同じように保てるようにする仕組みが必要ですね・・・」

在部署目标服务器上存在差异,导致无法获得预期行为的情况。
这个问题的根本原因在于允许有可变的基础设施。
我们开发的应用程序总是不可避免地依赖于某些东西。
操作系统当然是其中之一,还有诸如CPU、内存等计算机资源、语言运行时、库、作为应用程序内部的另一个进程运行的应用程序等等,都是我们的应用程序所依赖的各种要素。
如果每个服务器上部署的应用程序本身相同,那么排除应用程序所依赖的环境差异将是解决这个问题的捷径。

基础设施即代码(Infrastructure as Code)和不变基础设施(Immutable Infrastructure)。

基础设施即代码和不可变基础设施是近年来提出的解决此问题的强有力思路。
基础设施即代码是通过代码定义基础设施构建的思路。
通过以代码方式定义服务器的配置、要安装的库和工具等,利用Chef或Ansible等自动配置工具来构建服务器。
减少手动操作,将重点放在代码上,从而更容易复制多个相同配置的服务器。
然而,基础设施即代码并不是万能的。
比如,假设通过自动配置工具执行以下代码:

$ nodebrew install-binary stable

使用Node.js的版本管理工具nodebrew来安装稳定版的版本。
由于稳定版本会经常变动,所以无论何时执行这样的操作,都不能保证获得相同的结果。

为了避免环境差异问题,保持幂等性,即使何时何地执行都能保证相同的结果,变得非常重要。

应用程序依赖的所有运行时和库都应该编写代码以确保安装特定版本。
然而,即使基础架构是以代码为基础进行管理,处理保证幂等性的代码也需要花费时间来将配置应用于所有服务器,尤其是在服务器数量较多的情况下。
这就是Immutable Infrastructure的出现。
Immutable Infrastructure是保存某一时间点服务器状态并使其可复制的理念。
最大的优点是始终使用已正确设置的服务器。
如果要对服务器进行更改,不是更新现有基础架构,而是重新创建并保存为新的服务器映像,以便复制。一旦设置好服务器,就不需要再次修改或删除,因此不必担心幂等性。
Docker是实现这些理念简单且低成本的工具。
Docker通过Dockerfile来管理配置,因此Infrastructure as Code成为Docker的重要原则。
Docker使用容器化技术,不同于主机化技术复制了操作系统的OS部分,而是与主机操作系统共享了大部分OS部分。
因此,启动时间仅为几秒钟。这种速度极大地缩短了开发的交付时间。启动速度快,与重新创建基础结构的Immutable Infrastructure相契合。
Docker可以通过Docker映像(Dockerfile)来以代码方式管理配置,并且能够快速丢弃现有容器并重新构建。
可以说,Docker是一个功能齐全且方便使用的工具,同时兼具Infrastructure as Code和Immutable Infrastructure这两个方面的功能。

Docker在基础架构管理和部署方面的思想也是其优点之一。 传统方法中,我们需要将创建的应用程序部署到某个服务器(基础架构)上,基础架构的复制和应用程序的部署是完全分离的工作。 这种分离也造成了环境差异的温床。 Docker容器类似于将操作系统(基础架构)和应用程序打包在一起的盒子。 Docker镜像的构建可以同时构建基础架构和应用程序。 由于没有分离,工作环境的差异不容易产生。 容器可以保存为Docker镜像,并且可以重复使用。 Docker的重要魅力之一是能够同时管理应用程序和基础架构,从而实现高度可移植性。 创建的Docker镜像可以在装有Docker的任何机器上运行。 可以在运行在服务器上的Docker容器中运行开发者的Docker环境。 像SaaS CI、CircleCI 2.0和Codeship这样的服务可以使用Docker进行持续集成,从而可以应用创建的Docker镜像进行端到端测试等应用。

应用程序配置管理的便利性

Docker容器类似于将应用程序和基础设施包装在一起的箱子。
只有通过组合多个应用程序和中间件,才能构建出一定规模的系统。
换句话说,如果不组合几个容器,系统将无法构建。
这需要对整个系统进行适当的配置管理。
当考虑使用Docker构建这样的系统时,需要逐个执行所需的容器。
虽然Docker简化了部署过程,但单独运行复杂的系统是一个困难的问题。
每个容器之间的依赖关系和执行顺序的错误会导致不正确的运行。事实上,即使不使用Docker,将多个应用程序和中间件组合起来并使其准确运行也是一项困难的任务。

Docker的容器编排系统

为了简化使用多个容器的应用程序的管理,Docker 提供了一个名为 Docker Compose 的工具。Docker Compose 可以使用 yaml 格式的配置文件来定义执行容器,定义依赖关系以及控制启动顺序。例如,对于一个需要 Redis 的 Web 应用程序,可以通过以下方式定义和执行 Web 应用程序容器和 Redis 容器的配置。

version: "3"
services:
  web:
    image: gihyodocker/web
    ports:
      - "3000:3000"
    environment:
      REDIS_TARGET: redis
    depends_on:
      - redis
  redis:
    image: "redis:alpine"

通过Docker和Docker Compose,原本复杂的多个应用程序和中间件的依赖关系现在可以通过代码进行简洁管理。

在需要处理大量流量或其他大量处理的系统中,需要准备多个已安装Docker的服务器(Docker节点),并部署足够数量的应用程序容器群到节点集群中。

Docker Swarm(Swarm Mode)不仅可以管理单个服务器上的Docker Compose,还可以跨多个服务器管理多个容器。Docker Swarm提供了更实用的功能,包括容器的扩缩、资源利用率以及负载均衡等。

此外,部署方面还提供了滚动更新(逐步准备新旧容器并逐步投入服务)的机制,具有操作上的重要优势。

将多个节点上的多个容器群进行管理的方法被称为容器编排。

在非容器环境下,需要构建一定程度的操作和自动化机制来考虑服务器资源的扩展和滚动更新。然而,在容器编排中,保证可用性的机制被默认地整合进来。

Kubernetes是在容器编排领域正在确立为事实标准的地位。Kubernetes是由Google开发的开源软件,凝聚了Google多年的容器运维经验。

与Docker Swarm相比,Kubernetes的功能更加强大,具有更高的可扩展性。

Docker不仅具有容器级别的便利性,还通过Docker Compose和Docker Swarm等生态系统的强大,可以完整地进行系统开发。

作为高级容器编排的选择之一,还有Kubernetes。

Docker的优点还包括丰富的与之兼容的周边产品。

广告
将在 10 秒后关闭
bannerAds