DOCKER 介绍

Docker是一个开源的容器引擎,它有助于更快地交付应用。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的任务,在Docker容器的处理下,只需要数秒就能完成。

Docker 是一个开源的应用容器引擎,基于 Go 语言开发。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker 应用场景

Web 应用的自动化打包和发布

自动化测试和持续集成、发布

在服务型环境中部署和调整数据库或其他的后台应用

使用Docker可以实现开发人员的开发环境、测试人员的测试环境、运维人员的生产环境的一致性。

1.架构

image-20200929090646773.png

Docker架构图

  • Docker daemon( Docker守护进程):Docker daemon是一个运行在宿主机( DOCKER-HOST)的后台进程。可通过 Docker客户端与之通信。
  • Client( Docker客户端):Docker客户端是 Docker的用户界面,它可以接受用户命令和配置标识,并与 Docker daemon通信。图中, docker build等都是 Docker的相关命令。
  • Images( Docker镜像):Docker镜像是一个只读模板,它包含创建 Docker容器的说明。它和系统安装光盘有点像,使用系统安装光盘可以安装系统,同理,使用Docker镜像可以运行 Docker镜像中的程序。
  • Container(容器):容器是镜像的可运行实例。镜像和容器的关系有点类似于面向对象中,类和对象的关系。可通过 Docker API或者 CLI命令来启停、移动、删除容器。
  • Registry:Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。 Docker Hub提供了庞大的镜像集合供使用。用户也可以将自己本地的镜像推送到Docker仓库供其他人下载。

Docker借鉴了标准集装箱的概念。标准集装箱将货物运往世界各地,Docker将这个模型运用到自己的设计中,唯一不同的是:集装箱运输货物,而Docker是 运输软件。

Docker 组成部分
image-20200929094721097.png

2. CentOS Docker 安装

Docker 支持以下的 64 位 CentOS 版本:

  • CentOS 7
  • CentOS 8
  • 更高版本…

2.1 CentOS 7 镜像下载

官网下载链接:http://isoredirect.centos.org/centos/7/isos/x86_64/

step1: 进入下载页,选择阿里云站点进行下载

Actual Country 国内资源 Nearby Countries 周边国家资源

阿里云站点:http://mirrors.aliyun.com/centos/7/isos/x86_64/

每个链接都包括了镜像文件的地址、类型及版本号等信息

选择当前国家资源区站点下载,获取资源速度比较快

step1: 进入阿里云站点,选择 CentOS-7-x86_64-DVD-2003.iso下载

各个版本的ISO镜像文件说明:

CentOS-7-x86_64-DVD-2003.iso 标准安装版(推荐)

CentOS-7-x86_64-Everything-2003.iso 完整版,集成所有软件(以用来补充系统的软件或者填充本地镜像)

CentOS-7-x86_64-LiveGNOME-2003.iso GNOME桌面版

CentOS-7-x86_64-LiveKDE-2003.iso KDE桌面版

CentOS-7-x86_64-Minimal-2003.iso 精简版,自带的软件最少

CentOS-7-x86_64-NetInstall-2003.iso 网络安装版(从网络安装或者救援系统)


2.2 使用官方安装脚本自动安装

安装命令如下:

  1. curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

TIPS:

在执行curl命令访问地址的时候,出现下面的错误。

  1. curl: (35) Encountered end of file

原因:服务器443端口未对外开放,需要在防火墙规则中将443端口打开即可。

或者 直接关闭防火墙(只限于测试环境哦)

2.3 手动安装

卸载旧版本

较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关的依赖项。

$ sudo yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine

安装 Docker Engine-Community

使用 Docker 仓库进行安装

在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker。

设置仓库

安装所需的软件包。yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。

  1. $ sudo yum install -y yum-utils \
  2. device-mapper-persistent-data \
  3. lvm2

选择国内的一些源地址:

2.4 阿里云

  1. $ sudo yum-config-manager \
  2. --add-repo \
  3. http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装 Docker Engine-Community

安装最新版本的 Docker Engine-Community 和 containerd,或者转到下一步安装特定版本:

  1. $ sudo yum install docker-ce docker-ce-cli containerd.io

如果提示您接受 GPG 密钥,请选是。

Docker 安装完默认未启动。并且已经创建好 docker 用户组,但该用户组下没有用户。

要安装特定版本的 Docker Engine-Community,请在存储库中列出可用版本,然后选择并安装:

1、列出并排序您存储库中可用的版本。此示例按版本号(从高到低)对结果进行排序。

$ yum list docker-ce —showduplicates | sort -r

docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable

2、通过其完整的软件包名称安装特定版本,该软件包名称是软件包名称(docker-ce)加上版本字符串(第二列),从第一个冒号(:)一直到第一个连字符,并用连字符(-)分隔。例如:docker-ce-18.09.1。

  1. $ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

启动 Docker。

  1. $ sudo systemctl start docker

通过运行 hello-world 映像来验证是否正确安装了 Docker Engine-Community 。

  1. $ sudo docker run hello-world

Ubuntu16.04+、Debian8+、CentOS7

对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):

  1. [roo@hadoop docker]$ sudo touch daemon.json
  2. [roo@hadoop docker]$ sudo vim daemon.json
  1. {
  2. "registry-mirrors":["https://registry.docker-cn.com"]
  3. }

之后重新启动服务:

  1. $ sudo systemctl daemon-reload
  2. $ sudo systemctl restart docker

执行过程如果提示报错信息: Job for docker.service failed because the control process exited with error code. See “systemctl status docker.service” and “journalctl -xe” for details.

使用命令: systemctl status docker.service

查看启动信息与状态信息:

解决过程如下:

本机环境是VirtualBox上安装的CentOS7。

安装Docker

1.查看内核版本
uname -r 本机<内核版本: 3.10.0-327.el7.x86_64>

2.把yum包更新到最新
sudo yum update

3.安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

4.设置yum源
sudo yum-config-manager —add-repo https://download.docker.com/linux/centos/docker-ce.repo

5.查看仓库中docker版本
yum list docker-ce —showduplicates | sort -r

  1. 安装docker
    sudo yum install docker-ce
  2. 启动Docker,设置开机启动,停止Docker
    sudo systemctl start docker
    sudo systemctl enable docker
    sudo systemctl stop docker
  3. 查看版本
    ``` sudo systemctl restart docker 如果此步成功之后,查询docker的版本

docker version

  1. 9.使用一下确认是否启动成功,使用search 查一下<br />docker search mysql
  2. 10.查看日志状态成功日志<br />systemctl status docker.service
  3. 卸载Docker,对于旧版本没安装成功,卸掉。
  4. 1.查询安装过的包<br />yum list installed | grep docker<br />本机安装过旧版本<br />docker.x86_64,docker-client.x86_64,docker-common.x86_64
  5. 2.删除安装的软件包<br />yum -y remove docker.x86_64<br />yum -y remove docker-client.x86_64<br />yum -y remove docker-common.x86_64
  6. <a name="59436012"></a>
  7. ##### 重新启动DOCKER服务

root@hadoop docker]$ sudo systemctl restart docker

  1. <a name="0ab7f471"></a>
  2. # 3. 使用DOCKER
  3. <a name="dbf42faf"></a>
  4. # 3.1 Docker Hello World
  5. Docker 允许你在容器内运行应用程序, 使用 **docker run** 命令来在容器内运行一个应用程序。
  6. 输出Hello world

~$ docker run ubuntu:15.10 /bin/echo “Hello world” Hello world

![image-20200925091739429.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627343893982-f177f8ca-dbdf-4a4b-a9bd-17444863bebf.png#height=92&id=ufb8137a5&margin=%5Bobject%20Object%5D&name=image-20200925091739429.png&originHeight=184&originWidth=769&originalType=binary&ratio=1&size=25432&status=done&style=none&width=384.5)

各个参数解析:

- **docker:** Docker 的二进制执行文件。
- **run:** 与前面的 docker 组合来运行一个容器。
- **ubuntu:15.10** 指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。
- **/bin/echo "Hello world":** 在启动的容器里执行的命令

以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。

<a name="4b78ab15"></a>
## 3.2 运行交互式的容器

我们通过 docker 的两个参数 -i -t,让 docker 运行的容器实现**"对话"**的能力:

~$ docker run -i -t ubuntu:15.10 /bin/bash root@0123ce188bd8:/#

![image-20200925092302885.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627343916269-f057e9d7-6c9f-4400-9fda-ae57df6fddfc.png#height=97&id=uc79c8632&margin=%5Bobject%20Object%5D&name=image-20200925092302885.png&originHeight=193&originWidth=1153&originalType=binary&ratio=1&size=25491&status=done&style=none&width=576.5)


各个参数解析:

- **-t:** 在新容器内指定一个伪终端或终端。
- **-i:** 允许你对容器内的标准输入 (STDIN) 进行交互。

注意第二行 **root@0123ce188bd8:/#**,此时我们已进入一个 ubuntu15.10 系统的容器

我们尝试在容器中运行命令 **cat /proc/version**和**ls**分别查看当前系统的版本信息和当前目录下的文件列表

root@0123ce188bd8:/# cat /proc/version

Linux version 4.4.0-151-generic (buildd@lgw01-amd64-043) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10) ) #178-Ubuntu SMP Tue Jun 11 08:30:22 UTC 2019

root@0123ce188bd8:/# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

root@0123ce188bd8:/#


我们可以通过运行 exit 命令或者使用 CTRL+D 来退出容器。

root@0123ce188bd8:/# exit exit root@hadoop:~#


注意第三行中 **root@hadoop:~#** 表明我们已经退出了当期的容器,返回到当前的主机中。

<a name="1d564a57"></a>
## 3.3 启动容器(后台模式)

使用以下命令创建一个以进程方式运行的容器

~$ docker run -d ubuntu:15.10 /bin/sh -c “while true; do echo hello world; sleep 1; done” 2b1b7a428627c51ab8810d541d759f072b4fc75487eed05812646b8534a2fe63


在输出中,我们没有看到期望的 "hello world",而是一串长字符

**2b1b7a428627c51ab8810d541d759f072b4fc75487eed05812646b8534a2fe63**

这个长字符串叫做容器 ID,对每个容器来说都是唯一的,我们可以通过容器 ID 来查看对应的容器发生了什么。

首先,我们需要确认容器有在运行,可以通过 **docker ps** 来查看:

~$ docker ps CONTAINER ID IMAGE COMMAND …
5917eac21c36 ubuntu:15.10 “/bin/sh -c ‘while t…” …

![image-20200925093025841.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627343945195-c87f131d-3f67-4b43-802d-3054c5a50bf0.png#height=56&id=u0ad7c673&margin=%5Bobject%20Object%5D&name=image-20200925093025841.png&originHeight=112&originWidth=1068&originalType=binary&ratio=1&size=13852&status=done&style=none&width=534)


输出详情介绍:

**CONTAINER ID:** 容器 ID。

**IMAGE:** 使用的镜像。

**COMMAND:** 启动容器时运行的命令。

**CREATED:** 容器的创建时间。

**STATUS:** 容器状态。

状态有7种:

- created(已创建)
- restarting(重启中)
- running(运行中)
- removing(迁移中)
- paused(暂停)
- exited(停止)
- dead(死亡)

**PORTS:** 容器的端口信息和使用的连接类型(tcp\udp)。

**NAMES:** 自动分配的容器名称。

在宿主主机内使用 **docker logs** 命令,查看容器内的标准输出:

:~$ docker logs 31212910c5a6

![image-20200925093219988.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627343961913-64e1ffca-80ec-45d7-9411-ba995df777d3.png#height=209&id=u9e664705&margin=%5Bobject%20Object%5D&name=image-20200925093219988.png&originHeight=418&originWidth=1044&originalType=binary&ratio=1&size=36789&status=done&style=none&width=522)

<a name="bdf4cbb1"></a>
## 3.4 停止容器

我们使用 **docker stop** 命令来停止容器:

sudo docker stop 31212910c5a6

![image-20200925093624717.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627343978568-51f39229-7690-47f7-9367-7dd3f1cc6b9d.png#height=68&id=u8617bb88&margin=%5Bobject%20Object%5D&name=image-20200925093624717.png&originHeight=135&originWidth=1069&originalType=binary&ratio=1&size=13483&status=done&style=none&width=534.5)


通过 **docker ps** 查看,容器已经停止工作:

sudo docker ps


可以看到容器已经不在了。

<a name="tips"></a>
#### tips

docker守护进程启动的时候,会默认赋予名字为docker的用户组读写Unix socket的权限,因此只要创建docker用户组,并将当前用户加入到docker用户组中,那么当前用户就有权限访问Unix socket了,进而也就可以执行docker相关命令

sudo groupadd docker #添加docker用户组( 可能用户组已经存在) sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中 newgrp docker #更新用户组 docker ps #测试docker命令是否可以使用sudo正常使用


<a name="df5301a8"></a>
# 4. Docker 容器使用

---

<a name="468290be"></a>
## 4.1 Docker 客户端

docker 客户端非常简单 ,我们可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项。

:~# docker


<a name="90945a3d"></a>
## 4.2 容器使用

<a name="dde7c093"></a>
### 获取镜像

如果我们本地没有 ubuntu 镜像,我们可以使用 docker pull 命令来载入 ubuntu 镜像:

$ docker pull ubuntu

![image-20200925094623757.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627343997683-e2452fe3-d9c0-4bae-9b2b-25593a324e7d.png#height=60&id=ue34609cd&margin=%5Bobject%20Object%5D&name=image-20200925094623757.png&originHeight=119&originWidth=964&originalType=binary&ratio=1&size=16568&status=done&style=none&width=482)


<a name="b093c1c3"></a>
### 启动容器

以下命令使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器:

$ docker run -it ubuntu /bin/bash


参数说明:

- **-i**: 交互式操作。
- **-t**: 终端。
- **ubuntu**: ubuntu 镜像。
- **/bin/bash**:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

要退出终端,直接输入 **exit**:

root@ed09e4490c57:/# exit


<a name="5957faef"></a>
### 4.3 启动已停止运行的容器

查看所有的容器命令如下:

$ docker ps -a


-a 显示所有状态的容器

使用 docker start 启动一个已停止的容器:

$ docker start e1fccc3b1db8


<a name="d7c3bf7e"></a>
### 4.4 后台运行

在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 **-d** 指定容器的运行模式。

$ docker run -itd —name ubuntu-test(不能和原来已经有的名重复) ubuntu /bin/bash


点击图片查看大图:<br />![docker-run-d.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344022503-f5a4f492-fd2c-4933-8a5d-f3f1b61567c8.png#height=30&id=ua308258f&margin=%5Bobject%20Object%5D&name=docker-run-d.png&originHeight=60&originWidth=1587&originalType=binary&ratio=1&size=5693&status=done&style=none&width=793.5)<br />![docker-run-d2.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344033820-32fda746-94b0-45de-879f-7a9526df89a4.png#height=38&id=ub876a737&margin=%5Bobject%20Object%5D&name=docker-run-d2.png&originHeight=76&originWidth=1751&originalType=binary&ratio=1&size=6227&status=done&style=none&width=875.5)


**注:**加了 **-d** 参数默认不会进入容器,想要进入容器需要使用指令 **docker exec**

--name ubuntu-test 中的 ubuntu-test名字可以自定义,表示指定一个名字。

<a name="8bf20644"></a>
### 4.5 停止一个容器

停止容器的命令如下:

$ docker stop <容器 ID> 或 [roo@hadoop ~]$ docker stop ubuntu-test2

![docker-stop-1.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344053313-939f4f64-5057-494a-97de-d0468dc8365c.png#height=28&id=u74efef18&margin=%5Bobject%20Object%5D&name=docker-stop-1.png&originHeight=55&originWidth=1001&originalType=binary&ratio=1&size=2194&status=done&style=none&width=500.5)


停止的容器可以通过 docker restart 重启:

$ docker restart <容器 ID>

![docker-stop-2.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344064199-7d75f623-88c1-4617-b179-679511c059f4.png#height=29&id=u27b7834c&margin=%5Bobject%20Object%5D&name=docker-stop-2.png&originHeight=58&originWidth=1001&originalType=binary&ratio=1&size=2031&status=done&style=none&width=500.5)


<a name="2750e84f"></a>
### 4.6 进入容器

在使用 **-d** 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:

- **docker attach**
- **docker exec**:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。

**attach 命令**

下面演示了使用 docker attach 命令。

$ docker attach 1e560fca3906 或 [roo@hadoop ~]$ docker attach ubuntu-test2


**注意:** 如果从这个容器退出,会导致容器的停止。(exit 之后再次 docker ps -a)

**exec 命令**

下面演示了使用 docker exec 命令。

docker exec -it 243c32535da7 /bin/bash 或 docker exec -it ubuntu-test /bin/bash

![image-20200925104108304.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344141702-ddddfe90-3611-400b-941c-b14c109ef1d4.png#height=66&id=ueabb1d76&margin=%5Bobject%20Object%5D&name=image-20200925104108304.png&originHeight=132&originWidth=1138&originalType=binary&ratio=1&size=18110&status=done&style=none&width=569)


**注意:** 如果从这个容器退出,不会导致容器的停止,这就是为什么推荐大家使用 **docker exec** 的原因。

更多参数说明请使用 **docker exec --help** 命令查看。

<a name="8715f865"></a>
#### tips:

想操作某个目录,或者某个目录下的文件,提示权限不够;

最简单的方法:chmod 777 文件/文件夹名称


赋给所有用户这个文件/文件夹的读,写,看权限;

<a name="8b6fe91e"></a>
### 4.7 导出和导入容器

**导出容器**

如果要导出本地某个容器,可以使用 **docker export** 命令。

$ docker export 1e560fca3906 > ubuntu.tar 或 [roo@hadoop ~]$ docker export ubuntu-test > /docker/ubuntu-test.tar


导出容器 1e560fca3906 快照到本地文件 ubuntu.tar。<br />![docker-export.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344159648-19fb1032-2520-4c2d-90ca-6a8508b2b97f.png#height=140&id=u917d7f4b&margin=%5Bobject%20Object%5D&name=docker-export.png&originHeight=280&originWidth=1572&originalType=binary&ratio=1&size=18377&status=done&style=none&width=786)


这样将导出容器快照到本地文件。

**导入容器快照**

可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:

tips: 如果碰到权限问题:

通过将用户添加到docker用户组可以将sudo去掉,命令如下

sudo groupadd docker #添加docker用户组

sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中

newgrp docker #更新用户组



[roo@hadoop ~]$ cat /docker/ubuntu-test.tar | docker import - test/ubuntu:v1

(其中,test/ubuntu是镜像名,:V1是TAG) sha256:f79568cd5576b8ab4eaa4bdb95ce869b37da16064d31d637c30f85be741717bf

导入后查询:(用docker images 命令查看镜像)

[roo@hadoop ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE test/ubuntu v1 f79568cd5576 2 minutes ago 72.9MB

![docker-import.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344174106-8de2d305-5a46-435c-87e7-4349d96ddbcd.png#height=112&id=u5aa21423&margin=%5Bobject%20Object%5D&name=docker-import.png&originHeight=224&originWidth=1041&originalType=binary&ratio=1&size=15409&status=done&style=none&width=520.5)


此外,也可以通过指定 URL 或者某个目录来导入,例如:(语法如下,前提是真的存在有效地址)

$ docker import http://example.com/exampleimage.tgz example/imagerepo


<a name="0543d464"></a>
### 4.8 删除容器

删除容器使用 **docker rm** 命令:

$ docker rm -f 1e560fca3906 or [roo@hadoop ~]$ docker rm -f magical_stonebraker

![image-20200925145622811.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344210120-aec0f458-d1fa-4335-836b-738ef1b1513f.png#height=228&id=u0a4c565e&margin=%5Bobject%20Object%5D&name=image-20200925145622811.png&originHeight=455&originWidth=1447&originalType=binary&ratio=1&size=89520&status=done&style=none&width=723.5)


下面的命令可以清理掉所有处于终止状态的容器。

$ docker container prune


<a name="cdf0b11f"></a>
## 5. 运行一个 web 应用

前面我们运行的容器并没有一些什么特别的用处。

接下来让我们尝试使用 docker 构建一个 web 应用程序。

我们将在docker容器中运行一个 Python Flask 应用来运行一个web应用。

:~# docker pull training/webapp # 载入镜像 :~# docker run -d -P training/webapp python app.py

![image-20200925152530726.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344238571-83266205-6591-4709-806d-82998f97c99b.png#height=167&id=uc560e130&margin=%5Bobject%20Object%5D&name=image-20200925152530726.png&originHeight=334&originWidth=1897&originalType=binary&ratio=1&size=51115&status=done&style=none&width=948.5)

![image-20200925152643195.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344254827-42eccfd9-4ce8-41dd-b971-f1e29e068aae.png#height=35&id=uc0fa6d6d&margin=%5Bobject%20Object%5D&name=image-20200925152643195.png&originHeight=70&originWidth=889&originalType=binary&ratio=1&size=8013&status=done&style=none&width=444.5)


参数说明:

- **-d:**让容器在后台运行。
- **-P:**将容器内部使用的网络端口随机映射到我们使用的主机上。

---

<a name="bc96ae56"></a>
## 5.1 查看 WEB 应用容器

使用 docker ps 来查看我们正在运行的容器:<br />![image-20200927164116862.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344269511-e488c43d-420f-4e0a-aabb-c0d7fc1288fc.png#height=37&id=u0e1aa3db&margin=%5Bobject%20Object%5D&name=image-20200927164116862.png&originHeight=74&originWidth=1414&originalType=binary&ratio=1&size=12397&status=done&style=none&width=707)


这里多了端口信息。

Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32769 上。

这时我们可以通过浏览器访问WEB应用

先找到你当前虚拟机centos7的IP地址:<br />![image-20200927164447982.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344283363-c936e747-be8e-41fe-b07e-425387c3b4a1.png#height=173&id=u56d17b06&margin=%5Bobject%20Object%5D&name=image-20200927164447982.png&originHeight=346&originWidth=798&originalType=binary&ratio=1&size=53836&status=done&style=none&width=399)


然后打开firefox打开以下地址:<br />![image-20200927164554084.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344294533-dcc3c95d-4d5b-4b92-bccc-da3d2e1bd978.png#height=81&id=udcb7df6d&margin=%5Bobject%20Object%5D&name=image-20200927164554084.png&originHeight=161&originWidth=956&originalType=binary&ratio=1&size=22434&status=done&style=none&width=478)


我们也可以通过 -p 参数来设置不一样的端口:

:~$ docker run -d -p 5000:5000 training/webapp python app.py


**docker ps**查看正在运行的容器

容器内部的 5000 端口映射到我们本地主机的 5000 端口上。

<a name="6fa56f11"></a>
## 5.2 网络端口的快捷方式

通过 **docker ps** 命令可以查看到容器的端口映射,**docker** 还提供了另一个快捷方式 **docker port**,使用 **docker port** 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。

上面我们创建的 web 应用容器 ID 为 **bf08b7f2cd89** 名字为 **wizardly_chandrasekhar**。

我可以使用 **docker port bf08b7f2cd89** 或 **docker port wizardly_chandrasekhar**

来查看容器端口的映射情况。

:~$ docker port bf08b7f2cd89 5000/tcp -> 0.0.0.0:5000

:~$ docker port wizardly_chandrasekhar 5000/tcp -> 0.0.0.0:5000


<a name="09c44be4"></a>
## 5.3 检查 WEB 应用程序

使用 **docker inspect** 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。

:~$ docker inspect wizardly_chandrasekhar


<a name="a41bf547"></a>
## 5.4 停止 WEB 应用容器

:~$ docker stop wizardly_chandrasekhar
wizardly_chandrasekhar


<a name="80fb217a"></a>
## 5.5 重启WEB应用容器

已经停止的容器,我们可以使用命令 docker start 来启动。

:~$ docker start wizardly_chandrasekhar wizardly_chandrasekhar


docker ps -l 查询最后一次创建的容器:

docker ps -l

CONTAINER ID IMAGE PORTS NAMES bf08b7f2cd89 training/webapp … 0.0.0.0:5000->5000/tcp wizardly_chandrasekhar


正在运行的容器,我们可以使用 **docker restart** 命令来重启。

<a name="e4192904"></a>
## 5.6 移除WEB应用容器

我们可以使用 docker rm 命令来删除不需要的容器

:~$ docker rm wizardly_chandrasekhar
wizardly_chandrasekhar


删除容器时,容器必须是停止状态,否则会报如下错误

:~$ docker rm wizardly_chandrasekhar Error response from daemon: You cannot remove a running container bf08b7f2cd897b5964943134aa6d373e355c286db9b9885b1f60b6e8f82b2b85. Stop the container before attempting removal or force remove


<a name="375bf108"></a>
# 6. Docker 镜像

当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。

下面我们来学习:

- 1、管理和使用本地 Docker 主机镜像
- 2、创建镜像

---

<a name="e64e6dd2"></a>
## 6.1 列出镜像列表

我们可以使用 **docker images** 来列出本地主机上的镜像。

:~$ docker images


各个选项说明:

- **REPOSITORY:**表示镜像的仓库源
- **TAG:**镜像的标签
- **IMAGE ID:**镜像ID
- **CREATED:**镜像创建时间
- **SIZE:**镜像大小

同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 15.10、14.04 等多个不同的版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。

所以,我们如果要使用版本为15.10的ubuntu系统镜像来运行容器时,命令如下:

:~$ docker run -t -i ubuntu:15.10 /bin/bash root@d77ccb2e5cca:/#


参数说明:

- **-i**: 交互式操作。
- **-t**: 终端。
- **ubuntu:15.10**: 这是指用 ubuntu 15.10 版本镜像为基础来启动容器。
- **/bin/bash**:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

如果要使用版本为 14.04 的 ubuntu 系统镜像来运行容器时,命令如下:

:~$ docker run -t -i ubuntu:14.04 /bin/bash root@39e968165990:/#


如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像。

<a name="1bba5535"></a>
## 6.2 获取一个新的镜像

当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull 命令来下载它。

:~$ docker pull ubuntu:13.10


下载完成后,我们可以直接使用这个镜像来运行容器。

---

<a name="a5fbc1e5"></a>
## 6.3 查找镜像

我们可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: [**https://hub.docker.com/**](https://hub.docker.com/)

我们也可以使用 docker search 命令来搜索镜像。比如我们需要一个 httpd 的镜像来作为我们的 web 服务。我们可以通过 docker search 命令搜索 httpd 来寻找适合我们的镜像。

:~$ docker search httpd #查找名字中包含httpd的镜像


结果说明如下:

NAME:** 镜像仓库源的名称

**DESCRIPTION:** 镜像的描述

**OFFICIAL:** 是否 docker 官方发布

**stars:** 类似 Github 里面的 star,表示点赞、喜欢的意思。

**AUTOMATED:** 自动构建。

<a name="9d30adaf"></a>
## 6.4 拖取镜像

我们决定使用上图中的 httpd 官方版本的镜像,使用命令 docker pull 来下载镜像。

:~$ docker pull httpd 或 [lee@localhost /]$ docker pull centos/httpd


<a name="bd24a1b6"></a>
## 6.5 删除镜像

镜像删除使用 **docker rmi** 命令,比如我们删除 hello-world 镜像:

$ docker rmi hello-world


<a name="TIPS"></a>
##### TIPS

[lee[@localhost ](/localhost ) /]$ docker rmi bf756fb1ae65 <br />Error response from daemon: conflict: unable to delete bf756fb1ae65 (must be forced) - image is being used by stopped container 8fd458f21577

错误解析:这是由于要删除的目标镜像中有容器存在,故无法删除镜像

解决办法:先删除镜像中的容器,再删除该镜像。<br />![990671-20190428152349092-386984855.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344394256-fe46e815-e331-44b0-8f46-d310c5b7b3ff.png#height=124&id=uc502dfe6&margin=%5Bobject%20Object%5D&name=990671-20190428152349092-386984855.png&originHeight=248&originWidth=796&originalType=binary&ratio=1&size=25291&status=done&style=none&width=398)


注意:容器的ID和镜像的ID是不一样的。看错误提示即可。

<a name="a74a26c0"></a>
## 6.6 创建镜像

当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。

- 1、从已经创建的容器中更新镜像,并且提交这个镜像
- 2、使用 Dockerfile 指令来创建一个新的镜像

<a name="1a8920da"></a>
### 6.7 更新镜像

更新镜像之前,我们需要使用镜像来创建一个容器。

:~$ docker run -t -i ubuntu:15.10 /bin/bash root@e218edb10161:/#


在运行的容器内使用 **apt-get update** 命令进行更新。

在完成操作之后,输入 exit 命令来退出这个容器。

此时 ID 为 e218edb10161 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本。

:~$ docker commit -m=”has update” -a=”jeflee2324” e218edb10161 jeflee2324/ubuntu:v2 sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8


各个参数说明:

- **-m:** 提交的描述信息
- **-a:** 指定镜像作者
- **e218edb10161:**容器 ID
- jeflee2324/ubuntu:v2:** 指定要创建的目标镜像名

我们可以使用 **docker images** 命令来查看我们的新镜像 **jeflee2324/ubuntu:v2**:

:~$ docker images

![image-20200927191029932.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344477253-eec1eadc-6c7f-4a5b-9576-90e9453e105f.png#height=127&id=udf7ff31b&margin=%5Bobject%20Object%5D&name=image-20200927191029932.png&originHeight=254&originWidth=1008&originalType=binary&ratio=1&size=39770&status=done&style=none&width=504)


使用我们的新镜像 **jeflee2324/ubuntu** 来启动一个容器

:~$ docker run -t -i jeflee2324/ubuntu:v2 /bin/bash
root@1a9fbdeb5da3:/#


<a name="5e1b7a66"></a>
### 6.8 构建镜像

我们使用命令 **docker build** , 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。

查看文件的内容: :~$ cat Dockerfile


Dockerfile 文件内容:

FROM centos:6.7 MAINTAINER Fisher “jeflee@sudops.com”

RUN /bin/echo ‘root:123456’ |chpasswd RUN useradd jeflee2324 RUN /bin/echo ‘jeflee2324:123456’ |chpasswd RUN /bin/echo -e “LANG=\”en_US.UTF-8\”” >/etc/default/local EXPOSE 22 EXPOSE 80 CMD /usr/sbin/sshd -D


每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。

第一条FROM,指定使用哪个镜像源

RUN 指令告诉docker 在镜像内执行命令,安装了什么。。。

将 /  目录下的Dockerfile 文件复制到 /docker目录下:

[lee@localhost /]$ cp Dockerfile /docker/

[lee@localhost /]$ cd /docker


然后,我们使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像。

[lee@localhost docker]$ docker build -t jeflee2324/centos:6.7 .


<a name="15151080"></a>
##### tips:

error checking context: 'no permission to read from '/boot/System.map-3.10.0-1127.el7.x86_64''.

注意: 不要在 / 下制作镜像<br />![image-20200927194403641.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344494321-25370619-6f8b-4405-b0b6-d3ea2f7afa30.png#height=411&id=ub7717a0c&margin=%5Bobject%20Object%5D&name=image-20200927194403641.png&originHeight=821&originWidth=809&originalType=binary&ratio=1&size=106119&status=done&style=none&width=404.5)


参数说明:

- **-t** :指定要创建的目标镜像名
- **.** :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径

使用      docker images     查看创建的镜像已经在列表中存在,镜像ID为 734b60d6fe64<br />![image-20200927194514485.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344508642-2a5c47a9-f929-4815-b788-482cd7e06df5.png#height=102&id=ud9cc90fe&margin=%5Bobject%20Object%5D&name=image-20200927194514485.png&originHeight=203&originWidth=832&originalType=binary&ratio=1&size=35684&status=done&style=none&width=416)


我们可以使用新的镜像来创建容器

runoob@runoob:~$ docker run -t -i jeflee2324/centos:6.7 /bin/bash

[root@10183b66f836 /]# id jeflee2324 #输入id为jeflee2324(已存在的用户名) 显示以下结果

id=500(jeflee2324) gid=500(jeflee2324) groups=500(jeflee2324)


从上面看到新镜像已经包含我们创建的用户 jeflee2324

<a name="a2679ea1"></a>
### 6.9 设置镜像标签

我们可以使用 docker tag 命令,为镜像添加一个新的标签。

[root@10183b66f836 /]# exit exit

[lee@localhost docker]$ docker tag 734b60d6fe64 jeflee2324/centos:new_tag_dev


docker tag 镜像ID,这里是 734b60d6fe64 ,用户名称、镜像源名(repository name)和新的标签名(tag)。

使用 docker images 命令可以看到,ID为734b60d6fe64的镜像 多一个 标签。<br />![image-20200927195346843.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344523232-389a2e4b-4c7e-4ec9-8eef-5de4844dea85.png#height=130&id=u657f449c&margin=%5Bobject%20Object%5D&name=image-20200927195346843.png&originHeight=259&originWidth=841&originalType=binary&ratio=1&size=45550&status=done&style=none&width=420.5)


<a name="140038c8"></a>
# 7 Docker 容器网络连接

前面我们实现了通过网络端口来访问运行在 docker 容器内的服务。

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 **-P** 或 **-p** 参数来指定端口映射。

下面我们来实现通过端口连接到一个 docker 容器。

---

<a name="268e2c8a"></a>
## 7.1 网络端口映射

我们创建了一个 python 应用的容器。(先判断docker是否已经启动 systemctl start docker)

:~$ docker run -d -P training/webapp python app.py


另外,我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

我们使用 **-P** 参数创建一个容器,使用 **docker ps** 可以看到容器端口 5000 绑定主机端口 32768。

我们也可以使用 **-p** 标识来指定容器端口绑定到主机端口。

两种方式的区别是:

- **-P :**是容器内部端口**随机**映射到主机的高端口。
- **-p :** 是容器内部端口绑定到**指定**的主机端口。

:~$ docker run -d -p 5000:5000 training/webapp python app.py

![image-20200928104529760.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344539613-2d7ecda3-c84f-462d-b2c4-4ad815a03d4c.png#height=66&id=u2347c407&margin=%5Bobject%20Object%5D&name=image-20200928104529760.png&originHeight=132&originWidth=1341&originalType=binary&ratio=1&size=24601&status=done&style=none&width=670.5)


另外,我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

:~$ docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py

![image-20200928104640025.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344550923-4e0a7d40-2a91-4f64-a47f-d71bb518b68d.png#height=80&id=u5562b2d7&margin=%5Bobject%20Object%5D&name=image-20200928104640025.png&originHeight=159&originWidth=1346&originalType=binary&ratio=1&size=30788&status=done&style=none&width=673)


这样我们就可以通过访问 127.0.0.1:5001 来访问容器的 5000 端口。

上面的例子中,默认都是绑定 tcp 端口,如果要绑定 UDP 端口,可以在端口后面加上 **/udp**。

:~$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

![image-20200928104741899.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344565000-4625bb81-ac8a-40a7-9c79-d29e9b9ba1dd.png#height=85&id=ubea77df4&margin=%5Bobject%20Object%5D&name=image-20200928104741899.png&originHeight=170&originWidth=1435&originalType=binary&ratio=1&size=34624&status=done&style=none&width=717.5)


**docker port** 命令可以让我们快捷地查看端口的绑定情况。

:~$ docker port happy_black 5000


<a name="373569a0"></a>
## 7.2 Docker 容器互联

端口映射并不是唯一把 docker 连接到另一个容器的方法。

docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。

docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。

---

<a name="1a3e8c68"></a>
### 7.3 容器命名

当我们创建一个容器的时候,docker 会自动对它进行命名。另外,我们也可以使用 **--name** 标识来命名容器,例如:

:~$ docker run -d -P —name jeflee01 training/webapp python app.py


使用 **docker ps** 命令来查看容器名称。

roo@hadoop:~$ docker ps -l

![image-20200928105132338.png](https://cdn.nlark.com/yuque/0/2021/png/12461785/1627344580534-38209300-ad54-420f-83a6-187f2a6fd3bc.png#height=71&id=u7bccd9f1&margin=%5Bobject%20Object%5D&name=image-20200928105132338.png&originHeight=141&originWidth=1348&originalType=binary&ratio=1&size=22720&status=done&style=none&width=674)


<a name="6f270013"></a>
### 7.4 新建网络

下面先创建一个新的 Docker 网络。

$ docker network create -d bridge test-net


并使用以下命令查询网络:

```javascript
[lee@localhost docker]$ docker network ls

image-20200928105342802.png

参数说明:

-d:参数指定 Docker 网络类型,有 bridge、overlay。

其中 overlay 网络类型用于 Swarm mode,暂时忽略它。

7.5 连接容器

运行一个容器并连接到新建的 test-net 网络:

$ docker run -itd --name test1 --network test-net ubuntu /bin/bash

打开新的终端,再运行一个容器并加入到 test-net 网络:

$ docker run -itd --name test2 --network test-net ubuntu /bin/bash

然后回到第一个终端,用 docker ps 进行查询
image-20200928105709907.png

下面通过 ping 来证明 test1 容器和 test2 容器建立了互联关系。

进入 test1 容器

docker exec -it test1 /bin/bash
然后执行ping命令
ping test2

如果 test1、test2 容器内中无 ping 命令,则在容器内执行以下命令安装 ping(即学即用:可以在一个容器里安装好,提交容器到镜像,在以新的镜像重新运行以上俩个容器)。

apt-get update
apt install iputils-ping

在 test1 容器输入以下命令:

点击图片查看大图:
image-20200928111713538.png

同理在 test2 容器也会成功连接到:(切换终端)

docker exec -it test2 /bin/bash

点击图片查看大图:
image-20200928112240364.png

这样,test1 容器和 test2 容器建立了互联关系。

如果你有多个容器之间需要互相连接,推荐使用 Docker Compose

8. Docker 仓库管理

仓库(Repository)是集中存放镜像的地方。以下介绍一下 Docker Hub。当然不止 docker hub,只是远程的服务商不一样,操作都是一样的。

8.1 Docker Hub

目前 Docker 官方维护了一个公共仓库 Docker Hub。

大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。

8.2 注册

在 https://hub.docker.com 免费注册一个 Docker 账号。

image-20200928140230981.pngimage-20200928140520818.png

登录和退出

登录需要输入用户名和密码,登录成功后,我们就可以从 docker hub 上拉取自己账号下的全部镜像。

$ docker login

image-20200928162116973.png

退出

退出 docker hub 可以使用以下命令:

$ docker logout

拉取镜像

你可以通过 docker search 命令来查找官方仓库中的镜像,并利用 docker pull 命令来将它下载到本地。

以 ubuntu 为关键词进行搜索:

$ docker search ubuntu

使用 docker pull 将官方 ubuntu 镜像下载到本地:

$ docker pull ubuntu

8.3 推送镜像

用户登录后,可以通过 docker push 命令将自己的镜像推送到 Docker Hub。

以下命令中的 username 请替换为你的 Docker 账号用户名。

$ docker tag ubuntu(REPOSITORY):18.04(TAG) username/ubuntu:18.04
或
[lee@localhost ~]$ docker tag centos:6.7 jeflee2324/centos:6.7

将自己的镜像推送到docker hub

[lee@localhost ~]$ docker push jeflee2324/centos:6.7

回到你的网站查看:https://hub.docker.com/

image-20200928163239943.png

9. Docker Dockerfile

9.1 什么是 Dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

9.2 使用 Dockerfile 定制镜像

如何运行 Dockerfile 文件来定制一个镜像

1、下面以定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)

在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:

FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

image-20200928163906533.png

image-20200928164022007.png

2、FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

RUN:用于执行后面跟着的命令行命令。有以下俩种格式:

shell 格式:

RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz “http://download.redis.io/releases/redis-5.0.3.tar.gz“
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget
&& wget -O redis.tar.gz “http://download.redis.io/releases/redis-5.0.3.tar.gz“
&& tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

9.3 开始构建镜像

在 Dockerfile 文件的存放目录下,执行构建动作。

以下示例,通过目录下的 Dockerfile 构建一个 nginx:test(镜像名称:镜像标签)。

注:最后的 . 代表本次执行的上下文路径。

$ docker build -t nginx:test .

image-20200928164623835.png

docker images #查看

image-20200928164819270.png

以上显示,说明已经构建成功。

9.4 上下文路径

上一节中,有提到指令最后一个 . 是上下文路径,那么什么是上下文路径呢?

$ docker build -t nginx:test .

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

9.5 指令说明

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[—chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 —entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

1、不传参运行

$ docker run  nginx:test    # EPOSITORY:AG

容器内会默认运行以下命令,启动主进程。

nginx -c /etc/nginx/nginx.conf

2、传参运行

$ docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

nginx -c /etc/nginx/new.conf

ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

ARG

构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 —build-arg <参数名>=<值> 来覆盖。

格式:

ARG <参数名>[=<默认值>]

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式:

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

EXPOSE

仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

格式:

EXPOSE <端口1> [<端口2>...]

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

格式:

WORKDIR <工作目录路径>

USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

格式:

USER <用户名>[:<用户组>]

HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

格式:

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

10. Docker 安装 Nginx

Nginx 是一个高性能的 HTTP 和反向代理 web 服务器,同时也提供了 IMAP/POP3/SMTP 服务 。

10.1、查看可用的 Nginx 版本

访问 Nginx 镜像库地址: https://hub.docker.com/_/nginx?tab=tags。

可以通过 Sort by 查看其他版本的 Nginx,默认是最新版本 nginx:latest。
docker-nginx1.png

你也可以在下拉列表中找到其他你想要的版本:
docker-nginx2.png

此外,我们还可以用 docker search nginx 命令来查看可用版本:

$ docker search nginx
NAME                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                     Official build of Nginx.                        3260      [OK]       
jwilder/nginx-proxy       Automated Nginx reverse proxy for docker c...   674                  [OK]
richarvey/nginx-php-fpm   Container running Nginx + PHP-FPM capable ...   207                  [OK]
million12/nginx-php       Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   67                   [OK]
maxexcloo/nginx-php       Docker framework container with Nginx and ...   57                   [OK]
...

10.2、取最新版的 Nginx 镜像

这里我们拉取官方的最新版本的镜像:

$ docker pull nginx:latest

docker-nginx3.png

10.3、查看本地镜像

使用以下命令来查看是否已安装了 nginx:

$ docker images

docker-nginx4.png

在上图中可以看到我们已经安装了最新版本(latest)的 nginx 镜像。

10.4、运行容器

安装完成后,我们可以使用以下命令来运行 nginx 容器:

$ docker run --name nginx-test -p 8080:80 -d nginx

参数说明:

  • —name nginx-test:容器名称。
  • -p 8080:80: 端口进行映射,将本地 8080 端口映射到容器内部的 80 端口。
  • -d nginx: 设置容器在在后台一直运行。

docker-nginx5.png

image-20200928170010770.png

10.5、安装成功(ifconfig )

最后我们可以通过浏览器可以直接访问 8080 端口的 nginx 服务:
image-20200928170212912.png

11. MySQL 部署

11.1 拉取镜像

# 搜索 mysql 镜像
docker search mysql

# 拉取MySQL 5.7镜像
docker pull centos/mysql-57-centos7

image-20200929102403970.png

11.2 创建容器

docker run -di --name=mysql5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql

-p 代表端口映射,格式为 宿主机映射端口:容器运行端口

-e 代表添加环境变量 MYSQL_ROOT_PASSWORD 是root用户的远程登陆密码(如果是在容器中使用root登录的话,那么其密码为空)
image-20200929104750711.png

11.3 操作容器 MySQL

# 拉取MySQL 5.7镜像
docker exec -it mysql5.7 /bin/bash

# 登录容器里面的mysql
mysql -u root -p

image-20200929105018268.png

11.4 远程登录 MySQL

# 查看ip;如果以后要内部连接该mysql,如其他容器中要连接mysql容器的mysql的时候,可以使用如下命令查看Ip
docker inspect mysql5.7

在vm centos7虚拟机上的终端输入:
[lee@localhost ~]$ docker inspect mysql5.7

image-20200929105757247.png

11.5 查看当前VM CENTOS7的虚拟机地址,用ifconfig命令来查看

image-20200929110257103.png

11.6 使用Navicat在windows中进行远程登录在docker容器中的mysql

image-20200929110432724.png

12. Tomcat部署

12.1 拉取镜像

# 拉取tomcat镜像
docker pull tomcat

指定版本
docker pull tomcat:8.0.52

12.2 创建容器

# 创建tomcat容器;并挂载了webapps目录
docker run -di --name=mytomcat -p 9000:8080 -v
 /usr/local/tomcat/webapps:/usr/local/tomcat/webapps tomcat

 #创建tomcat9.X容器;并挂载了webapps.dist目录
docker run -di --name=mytomcat3 -p 9000:8080 -v
 /usr/local/tomcat/webapps:/usr/local/tomcat/webapps.dist tomcat 

  #创建tomca8.0.52容器;并挂载了webapps.dist目录
docker run -di --name=mytomcat8052 -p 9000:8080 -v /usr/local/tomcat/webapps:/usr/local/tomcat/webapps tomcat:8.0.52 

# 如果出现 WARNING: IPv4 forwarding is disabled. Networking will not work.
#执行如下操作
# 1、编辑 sysctl.conf
vi /etc/sysctl.conf

# 2、在上述打开的文件中后面添加
net.ipv4.ip_forward=1

# 3、重启network
systemctl restart network

image-20200929155152348.png

测试访问宿主机的端口号为9000的 tomcat。地址:http://宿主机ip:9000,也可往/user/local/tomcat/webapps下部署应用,然后再访问。(在win10上访问vm centos7中的tomcat容器)