docker 入门上篇

docker 这么火,我怎么能不了解下?前端

从我听到的关于 docker 的关键词,诸如 容器go语言编写虚拟化打包移植等等,就以为它是一个逼格有点高的东西。并且这玩意彷佛不是给前端准备的,毕竟咱们前端只是写写页面( ̄∇ ̄),这东西太复杂了。node

最后我固然仍是去学习它,并慢慢尝试用它。你要问缘由,那就是真香。linux

本文涉及如下内容:nginx

  • Docker 用途理解
  • Docker 安装及加速器配置
  • Docker 相关概念理解,以及学习相关命令,如镜像命令和容器命令
  • Docker 数据卷和数据卷容器
  • Docker 安装 nginx 实践

理解 Docker 的用途

语言是苍白的,但我仍是想去说些什么。若是去搜索 docker 的定义,给出的答案就是一种容器引擎,开发者能够打包他们的应用以及依赖包到一个可移植的镜像中,而后发布到任何流行的 Linux或Windows 机器上。第一次看到这个解释时我是似懂非懂的,我把容器理解为一个盒子,而后把代码打包到这个盒子里,就能够移植到别处运行。做为页面仔,我也不知道理解的对不对,并且没弄懂这么作的具体意义,这种操做给个人感受就像是打包一个app,而后能够下载到别人手机上用。不知道是否是只有我这么认为。后来在看过不少关于 docker 的文章后,我才了解到 docker 的用途。git

docker 能够解决软件运行环境不一致所带来的一系列问题。你是否听过这样一个灵魂质问:“我明明在本地运行地好好的,怎么你线上就崩了???”github

这是由于开发环境和生产环境基本不同,代码在哪运行,就要从新配置一套环境,这样除了带来时间成本外,一个大问题就是生产环境可能部署了不止一个项目,它们所依赖的环境版本不同。好比我本地用 nodejs 最新版本开发好了一个项目,想要部署到服务器,可是服务器上已经部署了一个 nodejs 项目,而且使用的是好久好久之前的一个版本,此时再直接部署新项目显然就有很大的隐患了。虽然有其余办法解决,但有了 docker 后,一切变的更优雅了。redis

啰嗦了这么多,其实 docker 的做用就是把应用代码和所依赖的环境一块儿打包成一个文件,运行这个文件,会生成一个虚拟容器,代码在这个容器里运行,就像在物理机上运行同样,不受外界环境的影响。还有一个概念要了解一下,就是容器自己所处的环境,一般成为“宿主机”,这能够是一个 Linux 或 Windows 的机器。docker

总结成一句话就是:docker 是一种容器技术,主要解决代码跨环境迁移的问题json

安装 Docker

安装教程实在不少,我这里演示的是在一台 CentOS 7.5 64位 服务器上的安装,参考的 菜鸟教程。别的系统的安装也能够自行查看。ubuntu

首先安装所需的软件包:

sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
复制代码

使用如下命令来设置稳定的仓库:

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
复制代码

安装最新版本的 Docker Engine-Community 和 containerd:

sudo yum install docker-ce docker-ce-cli containerd.io
复制代码

安装完成后输入 docker version 验证是否安装成功。

配置镜像加速器

跟 github 相似,docker也有一个镜像存储库 DockerHub(关于镜像,后面会说),因为国内网络缘由,咱们在拉取一些已有镜像时会遇到困难,因此须要配置加速器。加速器有不少种,这里推荐使用阿里云的加速器,它是免费的,不须要购买任何东西。

登陆阿里云后搜索关键词 镜像服务,选择容器镜像服务:

第一次使用时,会让你设置登陆密码,设置一下便可:

而后在左侧菜单点击镜像加速器,右边能够看到给你提供了一个加速地址,这个地址每一个人的都不同。阿里云很贴心地在下方给出直接运行的命令代码,选择你的平台,复制粘贴全部代码,直接运行在终端便可:

运行结束后,可使用命令 cat /etc/docker/daemon.json 查看是否设置成功,结果以下:

{
  "registry-mirrors": ["https://55zqg9lk.mirror.aliyuncs.com"]
}
复制代码

若是你想替换别的加速地址,直接修改后面的地址便可,修改完不要忘记运行:

sudo systemctl daemon-reload
sudo systemctl restart docker
复制代码

了解 Docker 的基础概念

docker 有三个基本概念:

  • 镜像(Image):Docker 镜像(Image),就至关因而一个 root 文件系统。好比官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
  • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例同样,镜像是静态的定义,容器是镜像运行时的实体。容器能够被建立、启动、中止、删除、暂停等。
  • 仓库(Repository):仓库可看着一个代码控制中心,用来保存镜像。

再说一下,镜像 其实就是打包出来的包含代码和依赖环境的文件,咱们可使用别人制做好的镜像,也能够本身制做镜像。而 容器 就是根据镜像建立的,同一个镜像能够建立不少容器,就像对象的关系。

另外,Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和建立Docker容器,能够用一张图来了解:

咱们先看 Hosts,它是 Docker 主机,用于执行 Docker 守护进程和容器。它分为本地主机和远程主机,主机下包含 daemon(守护程序)container(容器)image(镜像)daemon是一个常驻在后台的系统进程,当咱们安装完成 Docker 后,它就存在。

Registries 是仓库,Docker 有一个官方的镜像仓库Docker Hub,与github相似,咱们能够获取或上传镜像。咱们也能够建立本身的私有镜像库。

Clients 是Docker客户端,经过命令行与守护进程通讯。

Docker 相关命令

Docker 命令能够分三部分来讲,即服务命令镜像命令容器命令

服务命令

服务命令指的是操做 daemon 服务的命令,操控的是 docker 进程。它主要包含5个:

  • 查看 docker 状态:systemctl status docker
  • 启动 docker 服务:systemctl start docker
  • 中止 docker 服务:systemctl stop docker
  • 重启 docker 服务:systemctl restart docker
  • 开机启动 docker 服务:systemctl enable docker

首先咱们能够查看一下当前 docker 服务状态,使用 systemctl status docker

绿色部分的 active (running) 就表示 docker 正在运行,咱们再来中止一次服务,并查看状态:

如图,inactive (dead) 就表示 docker 服务已中止。再试下重启服务:

开机启动命令这里就不演示了。

镜像命令

镜像命令用于操做镜像(images)相关。

查看镜像

查看本地全部镜像,可以使用命令:

docker images
复制代码

能够看到个人本地有一个 redis 的镜像,这是由于我提早安装了,若是没安装就是空的。显示结果的第一行是表头,分别表示为 镜像名称版本号镜像 id建立时间镜像大小

查看全部镜像的 id,可使用命令:

docker images -q
复制代码

我这里只有一个镜像,因此只显示了一个 id,若是有多个镜像的话会显示全部的镜像 id。

搜索镜像

有时候咱们并不知道库里是否有咱们须要的镜像,这时候就须要先搜索,使用命令:

docker search 镜像名称
复制代码

好比咱们来搜索 redis

如图所示,会将全部 redis 相关源信息打印出来,第一行依旧是头,依次表示为:名称描述star 数是不是官方出的自动构建

拉取镜像

拉取镜像即从 docker 仓库下载镜像到本地,使用命令:

docker pull 镜像名称
复制代码

或者下载指定版本:

docker pull 镜像名称:版本号
复制代码

注意,当不指定版本号时,默认下载最新版本(latest版)。另外要指定下载某个版本时,能够去 DockerHub 查看镜像对应的一些版本号,不要随便自定义版本号。下载就不演示了。

删除镜像

删除指定镜像,使用命令:

docker rmi 镜像id
复制代码

注意这里是要指定镜像的 id ,而不是名称。咱们能够先使用 docker images 来查看镜像的id,而后再来删除。删除 redis 测试:

第一步查看全部镜像时,显示有两个镜像,删除 redis 后再查看时只有一个了,说明删除成功。

另外,当一次删除多个镜像时,能够将镜像id依次输入进去,这样:

docker rmi id1 id2 id3...
复制代码

当要删除全部的镜像时,可使用这样一个组合命令:

docker rmi `docker images -q`
复制代码

这句命令的意思很明显,就是将 docker images -q 查询到的全部镜像 id 传给删除命令,以达到删除全部镜像的效果。

容器命令

容器命令用于操控容器相关,是比较重要的部分,咱们最终直接用于生产的也就是容器。

查看容器

查看本地全部正在运行中的容器,使用命令:

docker ps
复制代码

查看本地全部的容器(无论是否运行),使用命令:

docker ps -a
复制代码

因为我本地暂未有容器,因此两个命令结果都为空。结果中的表头含义依次为:容器 ID使用的镜像启动容器时运行的命令容器的建立时间容器状态容器的端口信息和使用的链接类型容器名称

建立并启动容器

容器是根据镜像建立的,若是本地有镜像,能够直接使用,若是没有,会自动下载镜像,而后再建立容器。建立容器使用命令:

docker run [OPTIONS] IMAGE [COMMAND]
复制代码

[OPTIONS] 是可选参数,IMAGE 是建立容器要根据的镜像,[COMMAND] 是启动容器后执行的命令,可选。

这里说一下 OPTIONS 参数,官方提供了不少可选参数,咱们不须要一开始就去认识全部的参数,后面遇到的会再说,这里先只列举几个经常使用的了解一下:

  • -i:以交互模式运行容器,保持容器运行状态,一般与 -t 同时使用;
  • -t:为容器从新分配一个伪终端,一般与 -i 同时使用;
  • -d:之后台模式运行容器,建立一个容器在后台运行,须要使用 docker exec 进入容器,退出后容器不会关闭;
  • --name:为建立的容器命名(注意这里是长参数)。

如今举例来建立一个容器,选取镜像 centos,使用如下命令:

docker run -it --name=c1 centos /bin/bash
复制代码

来分析下这句命令的含义:

首先参数 -it-i -t 的合并写法,linux 的基础知识就很少说了,这两个参数同时使用表示建立的是一个交互式容器,建立完成后会自动进入容器,退出容器后,容器会关闭。开始这里可能不太明白什么意思,日后看。

--name=c1 表示给这个容器取名为 c1,也能够不加等号 --name c1,另外若是不主动取名,会自动生成一个名字。

centos 是镜像名称,在使用一个镜像前最好先搜索是否有这个镜像,同时咱们也能够指定镜像的版本,即 centos:7

/bin/bash 是一个命令,他会在建立容器完成并进入容器时执行,非必须。

如今咱们在终端执行这句命令:

首先看图中红框里,由于本地没有 centos 这个镜像,因此会自动在远程仓库拉取这个镜像,而且由于没指定版本,因此下载的是最新版的,以后就根据这个镜像建立完成了容器。

建立完成后会自动进入容器里,此时注意绿框中的命令提示符,显然已经不是在宿主机的终端了,而是容器内部的终端(由于 -t 参数),因此此时再执行的命令只对容器内部有效。退出容器,可执行 exit 命令:

退出后能够看到命令提示符中显示的又是宿主机了。须要知道的是,此时退出容器后,容器是关闭了的,再次强调一下使用 -it 参数建立的容器是交互式容器,退出即关闭,不信的话能够执行 docker ps 命令查看执行中的容器,它并不在列。

上面这种交互式容器意味着咱们不能退出,否则就关闭了,因此不少时候咱们须要另一种方式建立容器,让它在后台一直运行。

咱们使用另一种方式建立容器,使用命令:

docker run -id --name=c2 centos
复制代码

这条命令,使用 -d 参数替换掉了 -t,表示建立的是一个后台运行的容器,同时去除掉了 /bin/bash命令,由于建立后不会进入容器,不须要执行命令。须要注意的是使用的仍是同一个镜像,同一个镜像能够建立不少容器。

运行结果:

能够看到,建立完成后只返回了容器id,并无进入容器内部,命令提示符显示仍是在宿主机终端上。但此时这个容器是在运行的,使用 docker ps 来验证:

咱们能够进入容器来操做它,进入容器的命令是 docker exec,咱们先执行 docker exec --help 看看它有什么要求:

能够看到它必需要跟上容器名和一个命令,因此咱们能够执行:

docker exec c2 /bin/bash
复制代码

可是这样执行,咱们就拿不到一个能够在容器内部执行的终端,因此还须要加上 -it 参数,以下:

docker exec -it c2 /bin/bash
复制代码

仍是根据命令提示符,咱们已经进入到容器内部,此时一样可使用 exit 命令退出容器,可是此时退出并不会关闭容器,始终在后台运行,只能手动关闭(关闭容器命令后面说)。

须要注意的是, docker exec 进入容器操做不是仅针对 -id 形式建立的容器,使用 -it 形式建立的容器退出后,也是要用这个命令从新进入,而且进入以前须要手动启动容器。

小结:此小节咱们知道建立容器有两种方式,使用 -it 参数建立的是交互式容器,建立完自动进入容器,退出时自动关闭容器。使用 -id 参数建立的是守护式容器,即建立完运行在后台,须要使用 docker exec 进入容器,使用 exit 退出,而且退出时不会关闭容器。

启动/中止容器

启动容器,使用命令:

docker start 容器ID或者容器名
复制代码

中止容器,使用命令:

docker stop 容器ID或者容器名
复制代码

在使用以前能够先用 docker ps -a 来查看容器的相关信息。

删除容器

删除容器使用命令:

docker rm 容器ID或者容器名
复制代码

注意不能删除正在运行的容器,须要先关闭容器,才能删除。

若是要一次删除全部容器,可使用这个命令:

docker rm `docker ps -aq`
复制代码

docker ps -aq 表示查询全部容器的id,而后将结果传给 docker rm,以完成删除全部。须要注意这里删除全部的前提是全部的容器都处于关闭状态。

查看某容器信息

要查看某一个容器的信息,可使用命令:

docker inspect 容器ID或者容器名
复制代码

数据卷

数据卷是什么?

数据卷简单来讲,就是宿主机中的一个特殊目录,它会与容器内目录造成映射关系。用一张图来表示层级关系以下:

数据卷有什么用?

有这样一个问题是否想过,就是当容器删除后,它产生的数据是否会销毁?答案是确定的,由于容器是隔离运行的,数据也是产生在容器内部而不是在宿主机上,当容器被销毁时,所产生的数据也会被销毁。这显然是不安全的,咱们须要对容器数据进行备份。而数据卷的做用就是用来作数据持久化的,它彻底独立与容器的生命周期,容器删除时也不会删除其挂载的数据卷。

配置数据卷的方式其实就是在建立容器的同时,使用 -v 参数来配置,方式以下:

docker run ... -v 宿主机文件夹:容器内文件夹 ...
复制代码

注意事项:

  • 文件夹路径要是绝对路径
  • 若是文件夹不存在,会自动建立
  • 能够挂载多个数据卷,几屡次使用 -v 参数

来举个例子:

docker run -it --name=c1 -v ~/data:/root/data_container centos /bin/bash
复制代码

建立完成后,能够在容器的 /root 中看到 data_container 这个文件夹。同时宿主机的 ~/data 文件夹也确定存在了,它就是数据卷。

怎么使用数据卷呢?其实当配置好了数据卷后,无论是在宿主机上的操做仍是在容器中的操做,都会自动同步。来举个例子,咱们在容器 /root/data_container 目录中建立一个文件 test.txt

接下来,在新窗口查看宿主机的 ~/data 目录下是否有 test.txt 文件:

显然,文件是被同步的。反过来在宿主机上的操做,也是同步到容器中的,这里就很少演示了。

正是由于数据卷的这种同步功能,因此能够用来进行两个容器之间的间接通讯,原理无非就是两个容器同时挂载到一个数据卷中,谁修改了,另外一个也会收到更新。

另外,你也能够挂载多个数据卷,像这样:

docker run -it --name=c2 -v ~/data1:/root/data1 -v ~/data2:/root/data2 centos /bin/bash
复制代码

数据卷容器

数据卷容器首先是一个容器,它挂载数据卷,而后其余容器经过挂载这个容器实现数据共享。一样用一张图表示:

数据卷容器至关于起了一个桥梁做用,它挂载数据卷,而后其余容器间要通讯时就不须要一一再与数据卷挂载,直接挂载到数据卷容器上便可,简化了操做。

首先咱们来建立数据卷容器 c3,(注意我每次举例前都清空了现有容器,因此一直能用重复的名称,容器名你们随意~)

docker run -it --name=c3 -v /volume centos /bin/bash
复制代码

与以前配置数据卷不一样,这里的 -v 参数后面只接了一个目录,这个目录是咱们自定义的,它是属于容器内的。强调一下,这个目录是属于容器内的,不是宿主机上的。此时建立后,宿主机上会自动生成一个目录来映射(图中的数据卷是自动生成的,不是手动配置的)。

当运行命令后,容器内部已经生成了 volume 目录,如今咱们回到宿主机环境,使用 docker inspect c3 命令来查看此容器的一些信息:

Mounts 数组中,“Source” 后面的就是宿主机上的数据卷,它是建立数据卷容器时自动建立的,“Destination” 表示目标地址,就是咱们建立数据卷容器的自定义的 volume 目录。

而后咱们在建立两个容器:

docker run -it --name=c1 --volumes-from c3 centos /bin/bash

docker run -it --name=c2 --volumes-from c3 centos /bin/bash
复制代码

使用到了 --volumes-from 参数,使得新建立的容器能够访问 c3数据卷容器 的数据卷,说白了就是受权 c1,c2 能够访问 c3 的数据卷,实现数据共享。

当咱们按照上面建立 c1 后,会发现目录下存在 volume 这个目录,说明绑定 c3 成功了,建立 c2 也是同理。

那么如今就来验证一下数据共享。咱们在 c2 的 volume 目录下建立一个 hello.txt 文件,而后去查看 c1,c3 以及宿主机上的目录是否同步。

如图所示,一切没毛病。

使用 docker 安装 nginx

这里简单演示一下使用 docker 来安装 nginx。

拉取现有 nginx 镜像,正常状况下载一个镜像前应该去先搜索,这里略过,默认安装最新版本:

docker pull nginx
复制代码

根据镜像建立 nginx 的容器:

docker run -id --name=nginx_c -p 8080:80 nginx
复制代码

这里又出现了一个新的参数 -p ,它的做用是端口映射,8080:80 的意思是将容器的 80 端口映射到宿主机的 8080 端口。

为何要端口映射?这是由于外部机器是不能直接访问到容器,可是外部机器与宿主机是能够链接的,同时容器也能够与宿主机链接,因此为了在外部机器上能够远程访问到容器,咱们须要把容器的服务端口映射到宿主机上。

执行命令以后,使用服务器的 ip 加 8080 端口访问测试,以下:

能够看到使用 docker 部署 nginx 是如此便捷。固然用于实际生产还须要一些配置,这里先很少讲了,之后慢慢来。

结尾

因为本人也是刚刚入门 docker ,因此文中有不对的地方仍是但愿各位童鞋们指出,先谢谢了。

docker 文章还会继续出,一来是为了加深的印象,二来我喜欢分享学会的知识,若是对你有帮助,务必要给个赞哦~