文章目录
- 虚拟化与容器化
- 什么是 Docker
- Docker 工作原理
- 安装 Docker
- Docker 核心概念
- Docker file
- Image
- Container
- Docker 流程示例
- Docker 常用命令
- Dockerfile 常用指令
- Docker 网络通信
- Docker Compose
- Docker Hub
虚拟化与容器化
虚拟化技术是一种将计算机物理资源进行抽象、转换为虚拟的计算机资源提供给程序使用的技术。
这里所指的计算机资源,就包括了 CPU 提供的运算控制资源,硬盘提供的数据存储资源,网卡提供的网络传输资源等。
通过虚拟化技术来管理计算机资源的方式,不但让我们对计算机资源的控制变得更加灵活,也大幅提高了计算机资源的使用率。
容器化是将应用程序或服务、其依赖项及其配置(抽象化为部署清单文件)一起打包为容器映像的一种软件开发方法。软件容器充当软件部署的标准单元,其中可以包含不同的代码和依赖项。
按照这种方式容器化软件,开发人员和 IT 专业人员只需进行极少修改或不修改,即可将其部署到不同的环境。
容器化应用程序在容器主机上运行,而容器主机在 OS(Linux 或 Windows)上运行。因此,容器的占用比虚拟机 (VM) 映像小得多。
什么是 Docker
在谈 Docker 之前,我们先回想下搭建服务的过程,无论是搭建后端服务,还是爬虫等,我们首先得在本机上配置语言相关的环境,如编译器,变量环境等等,有时候还得下载对应的数据库。反正就是需要一系列的环境准备,经常配置个老半天的还可能被某个步骤卡住了。
在本机开发完成,需要部署线上环境的时候,往往又得跑一遍相同环境配置,因为计算机环境不同,配置也并不会一帆风顺。明明在我本机上这样可行的,但是在他人机器上却不行了。
所以 docker 的出现就是为了解决服务迁移过程中的这种不确定性,既然环境不同会引起一系列差异问题出现,那我干脆连环境一起迁移好了。
类似于虚拟机,Docker 也是提供一份隔离环境,叫做容器。但是相比于虚拟机而已,它非常的节约资源,高效。
Docker 是一种开源的容器化平台,用于构建、发布和管理应用程序。
它可以将应用程序及其依赖项打包成一个独立的容器,使其可以在任何环境中运行,而不需要考虑底层操作系统或硬件架构的差异。
Docker 容器可以在云、物理服务器、虚拟机和本地计算机上运行,提高了应用程序的可移植性和可部署性。
Docker 平台包括以下主要组件:
-
Docker Engine:是 Docker 平台的核心组件,用于创建、运行和管理容器。
-
Docker Hub:是 Docker 的公共注册中心,用于存储和分享 Docker 镜像。
-
Docker Compose:是 Docker 平台的编排工具,用于在多个容器之间定义和管理应用程序的关系和依赖关系。
-
Docker Swarm:是 Docker 平台的集群管理工具,用于管理多个 Docker 主机上的容器和应用程序。
Docker 的优点包括:
-
简化应用程序部署和管理:Docker 可以将应用程序及其依赖项打包为一个容器,使其可以轻松地在任何环境中运行。
-
提高应用程序的可移植性和可部署性:Docker 容器可以在任何 Docker 主机上运行,而不需要考虑底层操作系统或硬件架构的差异。
-
提高应用程序的安全性:Docker 容器是隔离的,可以避免应用程序之间的干扰和攻击。
-
提高应用程序的可扩展性:Docker 容器可以快速地启动和停止,使应用程序可以根据需要动态扩展。
-
降低应用程序部署和管理的成本:Docker 可以提高应用程序的效率和可靠性,从而降低部署和管理的成本。
Docker
借助上述优势非常迅速的发展自身生态,近两年熟练使用 Docker
也已经频繁的出现在前端的 JD 中了,
所以各位前端们还不一起学起来!
Docker 工作原理
Docker 技术使用 Linux 内核和内核功能(例如 Control Groups 和 namespaces)来分隔进程,以便各进程相互独立运行。Docker 的实现,主要归结于三大技术:命名空间 (Namespaces) 、控制组 ( Control Groups ) 和联合文件系统 ( Union File System ) 。
这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用程序,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。
容器工具(包括 Docker)可提供基于镜像的部署模式。这使得它能够轻松跨多种环境,与其依赖程序共享应用或服务组。Docker 还可在这一容器环境中自动部署应用程序(或者合并多种流程,以构建单个应用程序)。
此外,由于这些工具基于 Linux 容器构建,使得 Docker 既易于使用,又别具一格 —— 它可为用户提供前所未有的高度应用程访问权限、快速部署以及版本控制和分发能力。
Docker 是一种容器化技术,它的工作原理可以简单地概括为将应用程序和其依赖项打包到一个容器中,使其能够在任何环境中运行。
安装 Docker
安装 (macOS)
brew install docker
如果你使用的是 Windows 电脑,需要购买支持虚拟化的版本。如 Win10 专业版,Win10 家庭版是不行的
- Mac:download.docker.com/mac/stable/…
- Windows:download.docker.com/win/stable/…
- Linux:get.docker.com/
安装后验证是否成功
docker -v
Docker 核心概念
Docker file
Dockerfile 是一个用来自定义构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明,类似 package.json,可以在其他镜像的基础上进一步配置我们的自定义镜像。
Dockerfile
就像是一个环境搭建手册,因为其中包含的就是一个构建容器的过程。
Image
镜像就是我们装机的时候需要的系统盘或者系统镜像文件,这里它负责创建 docker 容器。
Docker 会把应用程序及其依赖都打包在一个 image 文件里,这个 image 文件就是镜像,其实就是一个二进制文件。
在 docker 中实际安装的就是一个个的镜像,比如有很多官方现成的镜像:node、mysql、monogo、nginx 可以从远程仓库下载。
将本机配置好的环境和服务打包成镜像,有了镜像,别人就可以生产一模一样的环境和服务,不需要再处理计算机环境的差异。
Container
容器是由镜像生成的,就像安装系统时使用镜像文件生成一个系统
镜像运行之后就是容器,容器和镜像可以互相转换
容器与容器,容器和主机都是互相隔离的
Docker 流程示例
接下来我们以 nginx 为例简单示范一下 docker 工作流程
我们先来演示一下通过远程仓库下载构建镜像
第一步我们查找镜像
docker search nginx
找到镜像后下载镜像
docker pull nginx:latest
(这一步是不是很亲切,简直跟git和npm一模一样)
我们现在可以查看一下镜像列表
docker image ls
可以发现 nginx 已经在我们的镜像列表中啦
有了镜像之后,我们就可以通过镜像文件生成容器了,可以使用
docker run -d -p 8080:80 nginx
简单介绍一下参数
- -d 后台运行
- -p 端口映射 <计算机>:< 容器 > 即将对主机 8080 的访问 映射到对容器 80 端口的访问
- nginx 镜像名字
然后我们在浏览器输入 http://127.0.0.1:8080/
就可以看到 nginx 已经启动啦
是不是感觉 docker 很简单?
接下来我们来自定义一个镜像文件
我们先创建一个 hello-docker 文件夹,在里面创建一个 index.html 文件,内容为:
<h1>Hello docker</h1>
然后我们在文件夹中创建一个 Dockerfile
文件,内容为:
FROM nginx
COPY ./index.html /usr/share/nginx/html/index.html
EXPOSE 80
在这里我们介绍一下上面用到的 docker file 参数配置
- FROM :指定基础镜像,必须为第一个命令,有且只有一个
- COPY : 拷贝文件,将本地文件添加到容器中,在这里是将宿主机中的
./index.html
文件复制进容器里的/usr/share/nginx/html/index.html
- EXPOSE :指定于外界交互的端口
完成上述步骤后,此时文件结构应该是:
hello-docker
index.html
Dockerfile
下一步我们打包镜像,根据 dockerfile 先创建镜像
cd hello-docker/ # 进入刚刚的目录
docker image build ./ -t hello-docker:1.0.0 # 打包镜像
docker image build ./ -t hello-docker:1.0.0
的意思是:
基于路径./
(当前路径)打包一个镜像
镜像的名字是 hello-docker
,版本号是 1.0.0
该命令会自动寻找 Dockerfile
来打包出一个镜像
我们可以使用 docker images
来查看本机已有的镜像
我们找到刚刚打包好的镜像之后,就可以根据镜像创建容器了:
docker container create -p 2333:80 hello-docker:1.0.0
docker container start xxx # xxx 为上一条命令运行得到的结果
第一个命令我们使用 docker container create
来创建基于 hello-docker:1.0.0
镜像的一个容器
使用 -p
来指定端口绑定,将容器中的 80
端口绑定在宿主机的 2333
端口
执行完该命令,会返回一个容器 ID,第二个命令的 start 就是启动这个容器
启动后就能通过访问本机的 2333
端口来达到访问容器内 80
端口的效果了
然后在浏览器打开 127.0.0.1:2333
,就能看到我们写的内容了
当容器运行后,可以通过下面命令进入容器内部:
docker container exec -it xxx /bin/bash # xxx 为容器ID
原理实际上是启动了容器内的 /bin/bash
,此时就可以通过 bash shell
与容器内交互了,就像远程连接了 SSH 一样
我们来总结一下发生了什么:
- 写一个 Dockerfile
- 使用
docker image build
来将Dockerfile
打包成镜像- 使用
docker container create
来根据镜像创建一个容器- 使用
docker container start
来启动一个创建好的容器正如你说看到的,docker并没有那么难!
Docker 常用命令
$ docker images # 查看所有镜像
$ docker image pull 【imageName:version】 # 拉取下载镜像
$ docker build -f ./Dockerfile -t test:0.0.1 # 构建打包镜像
$ docker run -d -p 8080:8080 test:0.0.1 # 通过镜像文件生成运行容器
$ docker ps # 查看当前运行中的容器
$ docker ps -a # 查看所有容器,包括已停止的容器
$ docker start [容器ID/Name] # 启动选定的容器
$ docker stop [容器ID/Name] # 停止选定的容器
$ docker rmi [镜像ID] # 删除选定镜像
$ docker rm [容器ID/Name] # 删除选定的容器
$ docker exec -it [容器ID] /bin/sh # 进入容器
$ docker logs [容器ID] # 查看容器日志
$ docker search [images_name:tag] # 搜索镜像
$ docker restart [container_name/container_id] # 重启容器,在加入新的npm包依赖需要重新编译或者nginx容器的配置更新后使用重启
$ docker cp [container_id/container_name] : [文件目录] [主机目录] # 将容器文件拷贝到主机
$ docker cp [主机目录] [container_id/container_name] : [文件目录] # 将主机的目录拷贝到容器
Dockerfile 常用指令
总体上来说,我们可以将
Dockerfile
理解为一个由上往下执行指令的脚本文件。当我们调用构建命令让
Docker
通过我们给出的Dockerfile
构建镜像时,Docker 会逐一按顺序解析Dockerfile
中的指令,并根据它们不同的含义执行不同的操作。
如果进行细分,我们可以将 Dockerfile
的指令简单分为五大类。
- 基础指令:用于定义新镜像的基础和性质。
- 控制指令:是指导镜像构建的核心部分,用于描述镜像在构建过程中需要执行的命令。
- 引入指令:用于将外部文件直接引入到构建镜像内部。
- 执行指令:能够为基于镜像所创建的容器,指定在启动时需要执行的脚本或命令。
- 配置指令:对镜像以及基于镜像所创建的容器,可以通过配置指令对其网络、用户等内容进行配置。
- FROM : 指定基础镜像,必须为第一个命令,有且只有一个
- MAINTAINER : 创建者信息
- RUN : 用于在镜像容器中执行命令
- ADD : 将本地文件添加到容器中,tar 类型文件会自动解压 (网络压缩资源不会被解压),可以访问网络资源,类似 wget
- COPY : 功能类似 ADD,但是是不会自动解压文件,也不能访问网络资源
- CMD : 构建容器后调用,也就是在容器启动时才进行调用。CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令
- ENTRYPOINT: 配置容器,使其可执行化
- ENV :设置环境变量
- EXPOSE:指定于外界交互的端口,EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
- VOLUME : 用于指定持久化目录
- WORKDIR:工作目录,类似于 cd 命令,通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在#该目录下执行。
Docker 网络通信
Docker
能够在容器中营造独立的域名解析环境,这使得我们可以在不修改代码和配置的前提下直接迁移容器,Docker
会为我们完成新环境的网络适配。
对于这个功能,我们甚至能够在不同的物理服务器间实现,让处在两台物理机上的两个 Docker 所提供的容器,加入到同一个虚拟网络中,形成完全屏蔽硬件的效果。
宿主机的 IP 地址与容器 veth pair 的 IP 地址不在同一个网段,宿主机外的网络无法主动发现容器的存在,不能直接进行容器通信。
所以 Docker 提供了端口映射的方式,就是将宿主机上的端口流量映射转发到容器内的端口上。
我们在使用 docker run 创建 Docker 容器时,可以用 --net
选项指定容器的网络模式,Docker 有以下 4 种网络模式:
- host 模式,使用 --net=host 指定。
- container 模式,使用 --net=container:NAME_or_ID 指定。
- none 模式,使用 --net=none 指定。
- bridge 模式,使用 --net=bridge 指定,默认设置。
除这四种基本的之外,还支持各种自定义模型。
通常情况下,docker 使用网桥 + NAT网卡 的方式进行通信。Bridge 模式会为容器创建独立的网络 namespace ,拥有独立的网卡等网格栈。
在 Docker 网络中,有三个比较核心的概念,也就是:沙盒 (Sandbox)、网络 ( Network )、端点 ( Endpoint )
- 沙盒提供了容器的虚拟网络栈,也就是之前所提到的端口套接字、
IP
路由表、防火墙等的内容。其实现隔离了容器网络与宿主机网络,形成了完全独立的容器网络环境。 - 网络可以理解为
Docker
内部的虚拟子网,网络内的参与者相互可见并能够进行通讯。Docker
的这种虚拟网络也是于宿主机网络存在隔离关系的,其目的主要是形成容器间的安全通讯环境。 - 端点是位于容器或网络隔离墙之上的洞,其主要目的是形成一个可以控制的突破封闭的网络环境的出入口。当容器的端点与网络的端点形成配对后,就如同在这两者之间搭建了桥梁,便能够进行数据传输了
Docker Compose
Docker Compose
是对容器组合进行管理的多容器定义和运行软件
如果说 Dockerfile
是将容器内运行环境的搭建固化下来,那么 Docker Compose
我们就可以理解为将多个容器运行的方式和配置固化下来
如果将使用 Docker Compose
的步骤简化来说,可以分成三步。
- 如果需要的话,编写容器所需镜像的
Dockerfile
;(也可以使用现有的镜像) - 编写用于配置容器的
docker-compose.yml
; - 使用
docker-compose
命令启动应用
配置文件是 Docker Compose
的核心部分,我们正是通过它去定义组成应用服务容器群的各项配置,而编写配置文件,则是使用 Docker Compose
过程中最核心的一个步骤。
Docker Compose
的配置文件是一个基于 YAML
格式的文件。关于 YAML
的语法大家可以在网上找到,这里不再细说,总的来说,YAML
是一种清晰、简单的标记语言,你甚至都可以在看过几个例子后摸索出它的语法。
与 Dockerfile
采用 Dockerfile
这个名字作为镜像构建定义的默认文件名一样,Docker Compose
的配置文件也有一个缺省的文件名,也就是 docker-compose.yml
,如非必要,建议大家直接使用这个文件名来做 Docker Compose
项目的定义。
Docker Compose
配置文件里可以包含许多内容,从每个容器的各个细节控制,到网络、数据卷等的定义。
在 Docker Compose
里不直接体现容器这个概念,这是把 service
作为配置的最小单元。
虽然每个 service
里的配置内容就像是在配置容器,但其实 service
代表的是一个应用集群的配置。
每个 service
定义的内容,可以通过特定的配置进行水平扩充,将同样的容器复制数份形成一个容器集群。
而 Docker Compose
能够对这个集群做到黑盒效果,让其他的应用和容器无法感知它们的具体结构。
Docker Hub
Docker Hub
是 Docker
官方建立的中央镜像仓库,除了普通镜像仓库的功能外,它内部还有更加细致的权限管理,支持构建钩子和自动构建,并且有一套精致的 Web 操作页面。
由于定位是 Docker
的中央镜像仓库系统,同时也是 Docker Engine
的默认镜像仓库,所以 Docker Hub
是开发者共享镜像的首选,那么也就意味着其中的镜像足够丰富。
常用服务软件的镜像,我们都能在 Docker Hub
中找到,甚至能找到针对它们不同用法的不同镜像。
同时,Docker Hub
也允许我们将我们制作好的镜像上传到其中,与广大 Docker
用户共享你的成果。
发布镜像需要如下步骤:
登陆 Docker Hub
,注册账号;
命令行执行 docker login
,之后输入我们的账号密码,进行登录;
推送镜像之前,需要打一个 Tag,执行 docker tag <image> <username>/<repository>:<tag>
这样我们就可以将我们制作好的镜像上传到Docker Hub
了。
到这相信大家已经对 Docker 有一个详细的了解,剩下关于 Docker 的学习和进阶还需要大家多实践