DOCKER 介绍
Docker是一个开源的容器引擎,它有助于更快地交付应用。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的任务,在Docker容器的处理下,只需要数秒就能完成。
Docker 是一个开源的应用容器引擎,基于 Go 语言开发。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 应用场景
Web 应用的自动化打包和发布
自动化测试和持续集成、发布
在服务型环境中部署和调整数据库或其他的后台应用
使用Docker可以实现开发人员的开发环境、测试人员的测试环境、运维人员的生产环境的一致性。
1.架构
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 组成部分
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 使用官方安装脚本自动安装
安装命令如下:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
TIPS:
在执行curl命令访问地址的时候,出现下面的错误。
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。
$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
选择国内的一些源地址:
2.4 阿里云
$ sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装 Docker Engine-Community
安装最新版本的 Docker Engine-Community 和 containerd,或者转到下一步安装特定版本:
$ 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。
$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
启动 Docker。
$ sudo systemctl start docker
通过运行 hello-world 映像来验证是否正确安装了 Docker Engine-Community 。
$ sudo docker run hello-world
Ubuntu16.04+、Debian8+、CentOS7
对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):
[roo@hadoop docker]$ sudo touch daemon.json
[roo@hadoop docker]$ sudo vim daemon.json
{
"registry-mirrors":["https://registry.docker-cn.com"]
}
之后重新启动服务:
$ sudo systemctl daemon-reload
$ 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
- 安装docker
sudo yum install docker-ce - 启动Docker,设置开机启动,停止Docker
sudo systemctl start docker
sudo systemctl enable docker
sudo systemctl stop docker - 查看版本
``` sudo systemctl restart docker 如果此步成功之后,查询docker的版本
docker version
9.使用一下确认是否启动成功,使用search 查一下<br />docker search mysql
10.查看日志状态成功日志<br />systemctl status docker.service
卸载Docker,对于旧版本没安装成功,卸掉。
1.查询安装过的包<br />yum list installed | grep docker<br />本机安装过旧版本<br />docker.x86_64,docker-client.x86_64,docker-common.x86_64
2.删除安装的软件包<br />yum -y remove docker.x86_64<br />yum -y remove docker-client.x86_64<br />yum -y remove docker-common.x86_64
<a name="59436012"></a>
##### 重新启动DOCKER服务
root@hadoop docker]$ sudo systemctl restart docker
<a name="0ab7f471"></a>
# 3. 使用DOCKER
<a name="dbf42faf"></a>
# 3.1 Docker Hello World
Docker 允许你在容器内运行应用程序, 使用 **docker run** 命令来在容器内运行一个应用程序。
输出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
参数说明:
-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 进行查询
下面通过 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 容器输入以下命令:
点击图片查看大图:
同理在 test2 容器也会成功连接到:(切换终端)
docker exec -it test2 /bin/bash
点击图片查看大图:
这样,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 账号。
登录和退出
登录需要输入用户名和密码,登录成功后,我们就可以从 docker hub 上拉取自己账号下的全部镜像。
$ docker login
退出
退出 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/
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
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 .
docker images #查看
以上显示,说明已经构建成功。
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 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
10.3、查看本地镜像
使用以下命令来查看是否已安装了 nginx:
$ docker images
在上图中可以看到我们已经安装了最新版本(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: 设置容器在在后台一直运行。
10.5、安装成功(ifconfig )
最后我们可以通过浏览器可以直接访问 8080 端口的 nginx 服务:
11. MySQL 部署
11.1 拉取镜像
# 搜索 mysql 镜像
docker search mysql
# 拉取MySQL 5.7镜像
docker pull centos/mysql-57-centos7
11.2 创建容器
docker run -di --name=mysql5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql
-p 代表端口映射,格式为 宿主机映射端口:容器运行端口
-e 代表添加环境变量 MYSQL_ROOT_PASSWORD 是root用户的远程登陆密码(如果是在容器中使用root登录的话,那么其密码为空)
11.3 操作容器 MySQL
# 拉取MySQL 5.7镜像
docker exec -it mysql5.7 /bin/bash
# 登录容器里面的mysql
mysql -u root -p
11.4 远程登录 MySQL
# 查看ip;如果以后要内部连接该mysql,如其他容器中要连接mysql容器的mysql的时候,可以使用如下命令查看Ip
docker inspect mysql5.7
在vm centos7虚拟机上的终端输入:
[lee@localhost ~]$ docker inspect mysql5.7
11.5 查看当前VM CENTOS7的虚拟机地址,用ifconfig命令来查看
11.6 使用Navicat在windows中进行远程登录在docker容器中的mysql
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
测试访问宿主机的端口号为9000的 tomcat。地址:http://宿主机ip:9000,也可往/user/local/tomcat/webapps下部署应用,然后再访问。(在win10上访问vm centos7中的tomcat容器)