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容器)