Docker基础篇

一、Docker概述

Docker为什么出现?

一款产品:开发–上线 两套环境!应用环境,应用配置!

开发—运维。问题:我在我的电脑可以运行!版本更新,导致服务不可用!对于运维来说,考验就十分大?

发布一个项目(jar+(Redis MySQL jdk ES)),项目能不能带上环境安装打包

传统:开发jar,运维来做!

现在:开发打包部署上线,一套流程做完!

用应用商城下载app举例

java–apk–发布(应用商店)–张三使用apk–安装即可用

java–jar(环境)–打包项目带上环境(镜像)—(Docker仓库:商店)—下载我们发布的镜像–直接运行即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LJHOl7OR-1637315135045)(docker知识总结.assets/image-20211020161356751.png)]

Docker的思想就来自于集装箱

JRE-多个应用(端口冲突)–原来都是交叉使用的

隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的

Docker通过隔离机制,可以将服务器利用到极致

【 > 可调出此格式】

Docker的历史

dotCloud

开源

虚拟机属于虚拟化技术。而Docker这样的容器技术,也是虚拟化技术,属于轻量级的虚拟化

虚拟机虽然可以隔离出很多“子电脑”,但占用空间更大,启动更慢,虚拟机软件可能还要花钱(例如

VMWare)。

而容器技术恰好没有这些缺点。它不需要虚拟出整个操作系统,只需要虚拟一个小规模的环境(类似“沙

箱”)。

它启动时间很快,几秒钟就能完成。而且,它对资源的利用率很高(一台主机可以同时运行几千个

Docker容器)。此外,它占的空间很小,虚拟机一般要几GB到几十GB的空间,而容器只需要MB级甚至

KB级。

vm: linux centos 原生镜像(一个电脑!) 隔离,需要开启多个虚拟机
docker: 隔离 镜像(不是完整的一个电脑,而只是一个最核心 的环境 4M+ jdk + mysql)十分小巧 运行镜像就可以了,十分小巧 秒级启动!

Docker为什么这么火?十分的轻巧!

Docker学习途径

Docker是基于Go语言实现的云开源项目。

官网:https://www.docker.com/

文档: https://docs.docker.com/ Docker的文档是非常详细的

仓库地址:https://hub.docker.com/

Docker能干嘛

虚拟机(virtual machine)就是带环境安装的一种解决方案。

它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。应用程序

对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文

件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,

操作系统和硬件三者之间的逻辑不变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z8VjJgzR-1637315135050)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211020165555492.png)]

虚拟机的缺点:

1、资源占用多

2、冗余步骤多

3 、启动慢

容器虚拟化技术

由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。

Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G6A7K8Y5-1637315135052)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211020165739028.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MamNUNaM-1637315135055)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211020170059063.png)]

比较 Docker 和传统虚拟化方式的不同之处:

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用

进程;

而容器内的应用进程直接运行于宿主机的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。

因此容器要比传统虚拟机更为轻便。

每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资

源。

DevOps(开发、运维)

更快速的应用交付和部署:

传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂

的配置才能正常运行。Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即

可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。

更便捷的升级和扩缩容:

随着微服务架构和Docker的发展,大量的应用会通过微服务方式架构,应用的开发构建将变成搭乐高积

木一样,每个Docker容器将变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业

务处理时,可通过镜像运行新的容器进行快速扩容,使应用系统的扩容从原先的天级变成分钟级甚至秒

级。

更简单的系统运维:

应用容器化运行后,生产环境运行的应用可与开发、测试环境的应用高度一致,容器会将应用程序相关

的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致性给应用带来影响,产生新的

BUG。当出现程序异常时,也可以通过测试环境的相同容器进行快速定位和修复。

**更高效的计算资源利用:**Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor [管理程序] 支持,所以在

一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。

二、Docker安装

Docker的基本组成

Docker的架构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gXX1gmeT-1637315135056)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211020173859906.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XBa7s7WF-1637315135057)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211020174339083.png)]

镜像(image)

Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很

多容器。 就好似 Java 中的 类和对象,类就是镜像,容器就是对象!

容器(container)

Docker 利用容器(Container)独立运行一个或一组应用。容器是用镜像创建的运行实例。

它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。

可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等) 和运行在其中的应用程序。

容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

仓库(repository)

仓库(Repository)是集中存放镜像文件的场所。

仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓

库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。

国内的公开仓库包括阿里云、网易云等

小结:

需要正确的理解仓储/镜像/容器这几个概念 :

  • Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个

可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生

成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。

同一个 image 文件,可以生成多个同时运行的容器实例。

  • image 文件生成的容器实例,本身也是一个文件,称为镜像文件。

  • 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,

也就是我们的容器

  • 至于仓库,就是放了一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候从仓库中拉下来

就可以了

环境说明

我们使用的是 CentOS 7 (64-bit)

目前,CentOS 仅发行版本中的内核支持 Docker。

Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。

查看自己的内核

uname -r 命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型

等)。

[root@kuangshen ~]# uname -r 
3.10.0-1160.el7.x86_64 

查看版本信息:

cat /etc/os-release

[root@kuangshen ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装步骤

1、官网安装参考手册: https://docs.docker.com/engine/install/centos/

2、确定你是CentOS7及以上版本,我们已经做过了

3、yum安装gcc相关环境(需要确保 虚拟机可以上外网 )

yum -y install gcc 
yum -y install gcc-c++

4、卸载旧版本

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

5、安装需要的软件包

yum install -y yum-utils

6、设置镜像仓库

# 错误 
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 
## 报错 
[Errno 14] curl#35 - TCP connection reset by peer 
[Errno 12] curl#35 - Timeout 

# 正确:推荐使用国内的 
yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo

【百度搜索docker的阿里云镜像地址】

7、更新yum软件包索引

yum makecache fast

8、安装 Docker CE

yum install docker-ce docker-ce-cli containerd.io

9、启动 Docker

systemctl start docker

10、测试命令

docker version 
docker run hello-world 
docker images

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJuow6hq-1637315135058)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021161148873.png)]

11、卸载

systemctl stop docker 
yum -y remove docker-ce docker-ce-cli containerd.io 
rm -rf /var/lib/docker

测试测试1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Bz3J7ke-1637315135059)(docker知识总结.assets/image-20211119172817934.png)]

测试2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1Y3xdDZ-1637315135060)(docker知识总结.assets/image-20211119173034006.png)]

安装过程出错:我在如下安装docker的命令到 yum -y install docker-ce 报错No package docker-ce available,解决方法如下

【第二种安装方法】

#1.下载关于docker的依赖环境

yum -y install yum-utils device-mapper-persistent-data lvm2

#2.设置一下下载Docker的镜像源 如果不设置,默认会从官网下载

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#3.安装Docker
#安装Docker缓存

yum makecache fast

#安装Docker的服务

yum -y install docker-ce

#4.启动,并设置为开机自动启动,测试
#启动Docker服务

systemctl start docker

#设置开机自动启动

systemctl enable docker

#测试

docker run hello-world

阿里云镜像加速

1、介绍:https://www.aliyun.com/product/acr

2、注册一个属于自己的阿里云账户,可复用淘宝账号【我的阿里云账号为邮箱/名字英文,密码为常用密码)

3、进入管理控制台设置密码,开通

4、查看镜像加速器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RKN8vFe6-1637315135061)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021162535941.png)]

5、配置镜像加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://b99zrcwv.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

回顾HelloWorld执行流程

1、启动hello-world

docker run hello-world

2、run干了什么?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pe7WVyjm-1637315135062)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021163154759.png)]

底层原理

Docker是怎么工作的

Docker是一个Client-Server结构的系统,Docker守护进程(即服务)运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gu3JcUtA-1637315135062)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021163956613.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ppwkV8Mf-1637315135063)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021164057105.png)]

为什么Docker比VM快

1、docker有着比虚拟机更少的抽象层。由亍docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SeRBA8aM-1637315135064)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021164544910.png)]

2、docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。因而避免引导、加载操作系统内核比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wRZOzI7c-1637315135065)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021164413960.png)]

三、Docker常用命令

帮助命令

docker version # 显示 Docker 版本信息。 

docker info # 显示 Docker 系统信息,包括镜像和容器数。。 

docker --help # 帮助,万能命令

帮助文档的地址: https://docs.docker.com/engine/reference/commandline/cli/

【所有命令可通过文档查看】

镜像命令

docker images

【管理镜像 】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-47vhFowd-1637315135066)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021172138623.png)]

docker search

【在Docker Hub中搜索镜像】

【✰学习思想:可通过docker官方文档查看docker search命令可用选项,也可xshell中执行 docker search --help 查看命令可用选项】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HZLkmg0v-1637315135068)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021172211854.png)]

例:列出STARS不小于3000的镜像

$ docker search mysql --filter=STARS=3000  
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   11556     [OK]
mariadb   MariaDB Server is a high performing open sou…   4401      [OK]

docker pull

【从注册表中拉取映像或存储库】

docker pull 镜像名[:tag]
分层下载,docker images的核心 (联合文件系统)
docker pull mysql 等价于
docker pull docker.io/library/mysql:latest # 真实位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPLAu5UF-1637315135069)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021172226100.png)]

支持的版本可在dockerhub查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8p9MWZOR-1637315135069)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211118160950924.png)]

docker rmi

【删除一个或多个镜像】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RRIYH3b3-1637315135070)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211021172257409.png)]

容器命令

说明:有镜像才能创建容器,我们这里使用 centos 的镜像来测试,就是虚拟一个 centos !

docker pull centos

docker run

【在新建容器中运行命令】

# 命令 
docker run [OPTIONS] IMAGE [COMMAND][ARG...] 
# 常用参数说明 
--name="Name" # 给容器指定一个名字 tomcat01 tomcat02 用于区分镜像
-d    # 后台方式运行容器,并返回容器的id
-i    # 以交互模式运行容器,通过和 -t一起使用 
-t    # 给容器重新分配一个终端,通常和 -i一起使用 
-it   # 使用交互方式运行,进入容器查看内容
-P    # 随机端口映射(大写) 
-p    # 指定端口映射(小写),一般可以有四种写法: 
        -p  ip:主机端口:容器端口
        -p  主机端口:容器端口 (常用) 
        -p  容器端口
        	容器端口 
# 测试 启动并进入容器
[root@kuangshen ~]# docker images 
    REPOSITORY TAG IMAGE ID CREATED SIZE 
    centos latest 470671670cac 3 months ago 237MB 
    
# 使用centos进行用交互模式启动容器,在容器内执行/bin/bash命令  /bin/bash为控制台位置
[root@kuangshen ~]# docker run -it centos /bin/bash 
[root@dc8f24dd06d0 /]# ls  # 注意地址,已经切换到容器内部了! 
    bin etc lib lost+found mnt proc run srv tmp var 
    dev home lib64 media opt root sbin sys usr

docker ps

【列出所有运行容器】

# 命令 
docker ps [OPTIONS] 
# 常用参数说明 
   # 列出当前所有正在运行的容器
-a # 列出当前所有正在运行的容器 + 历史运行过的容器
-l # 显示最近创建的容器 
-n=? # 显示最近创建的n个容器 
-q  # 静默模式,只显示容器编号

docker ps -a -n=1
docker ps -aq 

退出容器

exit  		#容器停止退出
Ctrl+P+Q    #容器不停止退出

启动/停止容器

docker start (容器id or 容器名)  # 启动容器 
docker restart (容器id or 容器名) # 重启容器 
docker stop (容器id or 容器名) # 停止容器 
docker kill (容器id or 容器名) # 强制停止容器

测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fsY3bm43-1637315135071)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211118172024207.png)]

docker ps查看正在运行的容器

删除容器

docker rm 容器id # 删除指定容器,不能删除正在运行的容器,如果强制删除 rm -f
docker rm -f $(docker ps -a -q) # 删除所有容器 
docker ps -a -q|xargs docker rm # 删除所有容器,xargs命令:将|前的结果作为参数传给docker rm

常用其他命令

后台启动容器

# 命令 docker run -d 容器名 
# 例子 
docker run -d centos 
# 启动centos,使用后台方式启动 
# 问题: 使用docker ps 查看,发现容器已经退出了! 
# 解释:Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令,就会自动退出。 
# 比如,你运行了nginx服务,但是docker前台没有运行应用,这种情况下,容器启动后,会立即自杀,因为他觉得没有程序了,所以最好的情况是,将你的应用使用前台进程的方式运行启动。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IgzKGc7z-1637315135072)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211118172858467.png)]

查看日志

# 命令 
docker logs -f -t --tail 容器id 
# 例子:我们启动 centos,并编写一段脚本来测试玩玩!最后查看日志 

[root@kuangshen ~]# docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done" 

[root@kuangshen ~]# docker ps 
CONTAINER ID IMAGE 
c8530dbbe3b4 centos 

# -t 显示时间戳 
# -f 打印最新的日志 
# --tail 数字 显示多少条! 
[root@kuangshen ~]# docker logs -tf --tail 10 c8530dbbe3b4 
2020-05-11T08:46:40.656901941Z kuangshen 
2020-05-11T08:46:41.658765018Z kuangshen 
2020-05-11T08:46:42.661015375Z kuangshen 
2020-05-11T08:46:43.662865628Z kuangshen 
2020-05-11T08:46:44.664571547Z kuangshen 
2020-05-11T08:46:45.666718583Z kuangshen 
2020-05-11T08:46:46.668556725Z kuangshen 
2020-05-11T08:46:47.670424699Z kuangshen 
2020-05-11T08:46:48.672324512Z kuangshen 
2020-05-11T08:46:49.674092766Z kuangshen
......

查看容器中运行的进程信息

【支持ps 命令参数】

# 命令 
docker top 容器id 
# 测试 
[root@kuangshen ~]# docker top c8530dbbe3b4 
UID PID PPID C STIME TTY TIME CMD root 27437 27421 0 16:43 ? 00:00:00 /bin/sh -c ....

查看容器/镜像的元数据 [重要命令]

# 命令 
docker inspect 容器id 
# 测试 
[root@kuangshen ~]# docker inspect c8530dbbe3b4 
[ 
	{ 
		# 完整的id,有意思啊,这里上面的容器id,就是截取的这个id前几位! 
		"Id": 
"c8530dbbe3b44a0c873f2566442df6543ed653c1319753e34b400efa05f77cf8", 
		"Created": "2020-05-11T08:43:45.096892382Z", 
		"Path": "/bin/sh", 
		"Args": [ 
			"-c", 
			"while true;do echo kuangshen;sleep 1;done" 
		],
		# 状态 
		"State": { 
			"Status": "running",
            "Running": true,
            "Paused": false, 
            "Restarting": false, 
            "OOMKilled": false
            "Pid": 27437,
            "ExitCode": 0,
            "Error": "", 
            "StartedAt": "2020-05-11T08:43:45.324474622Z", 
            "FinishedAt": "0001-01-01T00:00:00Z" 
		},
		// ........... 
]

进入正在运行的容器

# 命令1 
docker exec -it 容器id bashShell 

# 测试1 
[root@kuangshen ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED 
STATUS PORTS NAMES c8530dbbe3b4 centos "/bin/sh -c 'while t…" 12 minutes 
ago Up 12 minutes happy_chaum 

[root@kuangshen ~]# docker exec -it c8530dbbe3b4 /bin/bash 
[root@c8530dbbe3b4 /]# ps -ef 
UID PID PPID C STIME TTY TIME CMD 
root 1 0 0 08:43 ? 00:00:00 /bin/sh -c while true;do 
echo kuangshen;sleep 
root 751 0 0 08:56 pts/0 00:00:00 /bin/bash 
root 769 1 0 08:56 ? 00:00:00 /usr/bin/coreutils 
-- coreutils-prog-shebang=s 
root 770 751 0 08:56 pts/0 00:00:00 ps -ef 

# 命令2 
docker attach 容器id 
# 测试2 
[root@kuangshen ~]# docker attach c8530dbbe3b4 /bin/bash 
kuangshen
kuangshen 
kuangshen
kuangshen
...

[进入容器当前正在执行的终端]


# 区别 
# exec 是在容器中打开新的终端,并且可以启动新的进程
# attach 直接进入容器启动命令的终端,不会启动新的进程

从容器内拷贝文件到主机上

# 命令 
docker cp 容器id:容器内路径 目的主机路径 

# 测试 
#进入容器
[root@kuangshen ~]docker attach 402b62370ce1   
# 容器内执行,创建一个文件测试 
[root@c8530dbbe3b4 /]# cd /home 
[root@c8530dbbe3b4 home]# touch f1 
[root@c8530dbbe3b4 home]# ls
f1
[root@c8530dbbe3b4 home]# exit 
exit 

# linux复制查看,是否复制成功 
[root@kuangshen ~]# docker cp c8530dbbe3b4:/home/f1 /home 
[root@kuangshen ~]# cd /home 
[root@kuangshen home]# ls 
f1

#拷贝是一个手动过程,未来我们使用-v 卷的技术,可以实现容器内和主机的自动同步

学习方式:将所有命令敲一遍,自己记录笔记

小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3vKgG83V-1637315135072)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211022170200574.png)]

常用命令汇总

attach 	Attach to a running container # 当前 shell 下 
attach 连接指定运行镜像 
build 	Build an image from a Dockerfile 
# 通过 Dockerfile 定制镜像 
commit 	Create a new image from a container changes 
# 提交当前容器为新的镜像 
cp Copy files/folders from the containers filesystem to the host path 
#从容器中拷贝指定文件或者目录到宿主机中 
create 	Create a new container 	
# 创建一个新的容器,同 run,但不启动容器 
diff 	Inspect changes on a container's filesystem 	
# 查看 docker 容器变化 
events Get real time events from the server 
# 从 docker 服务获取容 器实时事件 
exec Run a command in an existing container 
# 在已存在的容器上运行命 令
export Stream the contents of a container as a tar archive 
# 导出容器的内 容流作为一个 tar 归档文件[对应 import ] 
history Show the history of an image 
# 展示一个镜像形成历史 
images List images 					
# 列出系统当前镜像 
import Create a new filesystem image from the contents of a tarball 
# 从 tar包中的内容创建一个新的文件系统映像[对应export] 
info Display system-wide information 
# 显示系统相关信息 
inspect Return low-level information on a container 
# 查看容器详细信息 
kill Kill a running container 
# kill 指定 docker 容 器
load Load an image from a tar archive 
# 从一个 tar 包中加载一个镜像[对应 save] 
login Register or Login to the docker registry server 
# 注册或者登陆一个 docker 源服务器 
logout Log out from a Docker registry server 
# 从当前 Docker registry 退出
logs Fetch the logs of a container 
# 输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
# 查看映射端口对应的容器内部源端口 
pause Pause all processes within a container 
# 暂停容器 
ps List containers 
# 列出容器列表 
pull Pull an image or a repository from the docker registry server 
# 从docker镜像源服务器拉取指定镜像或者库镜像 
push Push an image or a repository to the docker registry server 
# 推送指定镜像或者库镜像至docker源服务器 
restart Restart a running container 
# 重启运行的容器 
rm Remove one or more containers 
# 移除一个或者多个容器 
rmi Remove one or more images 
# 移除一个或多个镜像[无容器使用该 镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除] 
run Run a command in a new container 
# 创建一个新的容器并运行 一个命令 
save Save an image to a tar archive 
# 保存一个镜像为一个 tar 包[对应 load] 
search Search for an image on the Docker Hub 
# 在 docker hub 中搜 索镜像 
start Start a stopped containers 
# 启动容器 
stop Stop a running containers 
# 停止容器 
tag Tag an image into a repository 
# 给源中镜像打标签 
top Lookup the running processes of a container 
# 查看容器中运行的进程信息
unpause Unpause a paused container
# 取消暂停容器 
version Show the docker version information 
# 查看 docker 版本号 
wait Block until a container stops, then print its exit code 
# 截取容器停止时的退出状态值

作业练习

练习1:使用Docker 安装 Nginx

#1.搜索镜像
[root@aubin home]# docker search nginx
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                        15824     [OK]
......
#2.拉取镜像
[root@aubin home]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
eff15d958d66: Pull complete
1e5351450a59: Pull complete
2df63e6ce2be: Pull complete
9171c7ae368c: Pull complete
020f975acd28: Pull complete
266f639b35ad: Pull complete
Digest: sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

#3.启动镜像
[root@aubin home]# docker run -d --name mynginx -p 3500:80 nginx
9a40f986e38fa1dc7cc129eea3b81898f9056a34fe885739ca2a6e54b3da0f4a

#4.测试访问
[root@aubin home]# curl localhost:3500
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>


#5.进入容器
[root@aubin home]# docker exec -it mynginx /bin/bash
root@9a40f986e38f:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx

[root@9a40f986e38f:/# cd  /usr/share/nginx
[root@9a40f986e38f:/usr/share/nginx# ls
html
[root@9a40f986e38f:/usr/share/nginx# cd html
[root@9a40f986e38f:/usr/share/nginx/html# ls
50x.html  index.html
[root@9a40f986e38f:/usr/share/nginx/html# cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

虚拟机及外网均能访问nginx

虚拟机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o9ZzXK6i-1637315135073)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211119115004334.png)]

外网

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fK4KSW5M-1637315135074)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211119115141065.png)]

端口暴露的概念

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KPJ17AQZ-1637315135076)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211119111139674.png)]

#思考:我们以后要部署项目,还需要进入容器中,是不是十分麻烦,要是有一种技术,可以将容器 内和我们Linux进行映射挂载就好了?我们后面会将数据卷技术来进行挂载操作,也是一个核心内容,这里大家先听听名词就好,我们很快就会讲到!

练习2:使用docker安装 tomcat

# 官方文档的使用 
# -it :交互模式 
# --rm:容器启动成功并退出以后容器就自动移除,一般在测试情况下使用
docker run -it --rm tomcat:9.0 
#docker ps查看发现tomcat没有运行(镜像还在)

# 1、下载tomcat镜像
docker pull tomcat 
# 2、启动[容器外部3355可访问内部的8080端口] 
docker run -d -p 3355:8080 --name tomcat9 tomcat 
# 3、进入tomcat 
docker exec -it tomcat9 /bin/bash 
root@47d1276c20d6:/usr/local/tomcat/webapps# ls
root@47d1276c20d6:/usr/local/tomcat/webapps#
#发现问题:1.Linux命令少了 2.webapp没有内容
#原因:阿里云镜像的原因。默认是最下的镜像,所有不必要的都剔除掉,保证最小可运行的环境

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wVEkzoKX-1637315135077)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211119145443469.png)]

#可把webapp.dist的内容复制到webapp目录中
root@47d1276c20d6:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@47d1276c20d6:/usr/local/tomcat# ls webapps
ROOT  docs  examples  host-manager  manager

此时网址可访问到tomcat服务中webapp的内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PaVC8Bm-1637315135078)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211119150441885.png)]

作业3:使用docker 部署 es + kibana

# 我们启动es这种容器需要考虑几个问题
1、es暴露的端口很多 9200、9300 
2、数据卷的挂载问题 data、plugins、conf 
3、es十分耗内存 - "ES_JAVA_OPTS=-Xms512m -Xmx512m" 

#1、启动es测试
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag

# 2、启动之后很卡,使用 docker stats 容器id 查看下cpu状态 ,发现占用的很大


# 3、测试访问


# 4、增加上内存限制启动


# 5、启动之后,使用 docker stats 查看下cpu状态


# 6、测试访问,效果一样,ok!

# 思考:如果我们要使用 kibana , 如果配置连接上我们的es呢?网络该如何配置呢?

可视化

  • Portainer(先用这个)
docker run -d -p 8088:9000 \ 
--restart=always -v /var/run/docker.sock:/var/run/docker.sock -- privileged=true portainer/portainer
  • Rancher(CI/CD再用这个)
#安装rancher-server 
docker run --name rancher-server -p 8000:8080 -v /etc/localtime:/etc/localtime:ro -d rancher/server 
#安装agent 
docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.11 http://39.101.191.131:8000/v1/scripts/D3DBD43F263109BB881F:1577750400000:7M0y BzCw4XSxJklD7TpysYIpI

介绍:

Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。

如果仅有一个docker宿主机,则可使用单机版运行,Portainer单机版运行十分简单,只需要一条语句即可启动容器,来管理该机器上的docker镜像、容器等数据。

docker run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock -- privileged=true portainer/portainer

访问方式:http://IP:8088

首次登陆需要注册用户,给admin用户设置密码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUQfCCy1-1637315135079)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025104613712.png)]

单机版这里选择local即可,选择完毕,点击Connect即可连接到本地docker:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cnnHpc3z-1637315135080)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025104639641.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NgnZTkew-1637315135081)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025104654935.png)]

我们可以点击可视化界面来玩玩!

四、Docker镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

Docker镜像加载原理

UnionFS (联合文件系统)

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual fifilesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot fifile system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启

动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是

一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已

由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root fifile system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标

准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nqDEe99h-1637315135082)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025105625490.png)]

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G95jDcFb-1637315135083)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025105651547.png)]

对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

分层理解

分层的镜像

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GzsobGfH-1637315135084)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025105801845.png)]

思考:为什么Docker镜像要采用这种分层的结构呢?

最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过 docker image inspect 命令!

[root@kuangshen home]# docker image inspect redis:latest
[ 
	// ..... 
		"RootFS": { 
		"Type": "layers", 
		"Layers": [ "sha256:c2adabaecedbda0af72b153c6499a0555f3a769d52370469d8f6bd6328af9b13", "sha256:744315296a49be711c312dfa1b3a80516116f78c437367ff0bc678da1123e990", "sha256:379ef5d5cb402a5538413d7285b21aa58a560882d15f1f553f7868dc4b66afa8", "sha256:d00fd460effb7b066760f97447c071492d471c5176d05b8af1751806a1f905f8", "sha256:4d0c196331523cfed7bf5bafd616ecb3855256838d850b6f3d5fba911f6c4123", "sha256:98b4a6242af2536383425ba2d6de033a510e049d9ca07ff501b95052da76e894" 
		] 
	},
	"Metadata": { 
	"LastTagTime": "0001-01-01T00:00:00Z" 
	} 
  } 
]

理解:

所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之

上,创建新的镜像层。

举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qomT1Q9D-1637315135084)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025110040025.png)]

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oD9mo5jo-1637315135085)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025110130245.png)]

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件7 是文件 5 的一个更新版本。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0SBCskxi-1637315135086)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025110206090.png)]

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker 在 Windows 上仅支持 windowsfifilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nbQ7PFkw-1637315135087)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025110247328.png)]

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

镜像Commit

docker commit 从容器创建一个新的镜像

docker commit 提交容器副本使之成为一个新的镜像! 
# 语法 
docker commit -m="提交的描述信息" -a="作者" 容器id 要创建的目标镜像名:[标签名]
# 1、从Docker Hub 下载tomcat镜像到本地并运行 -it 交互终端 -p 端口映射 
docker run -it -p 8080:8080 tomcat 

# 注意:坑爹:docker启动官方tomcat镜像的容器,发现404是因为使用了加速器,而加速器里的 tomcat的webapps下没有root等文件! 
# 下载tomcat官方镜像,就是这个镜像(阿里云里的tomcat的webapps下没有任何文件) 
# 进入tomcat查看cd到webapps下发现全部空的,反而有个webapps.dist里有对应文件,cp -r 到webapps下! 
root@aba865b53114:/usr/local/tomcat# cp -r webapps.dist/* webapps 

# 2、删除上一步镜像产生的tomcat容器的文档 
docker ps # 查看容器id 
docker exec -it 容器id /bin/bash 
/usr/local/tomcat # ce webapps/ 
/usr/local/tomcat/webapps # ls -l # 查看是否存在 docs文件夹 /usr/local/tomcat/webapps # curl localhost:8080/docs/ 
# 可以看到 docs 返回的 内容
/usr/local/tomcat/webapps # rm -rf docs # 删除它 
/usr/local/tomcat/webapps # curl localhost:8080/docs/ # 再次访问返回404 

# 3、当前运行的tomcat实例就是一个没有docs的容器,我们使用它为模板commit一个没有docs的 tomcat新镜像, tomcat02 
docker ps -l # 查看容器的id 

# 注意:commit的时候,容器的名字不能有大写,否则报错:invalid reference format 
docker commit -a="kuangshen" -m="no tomcat docs" 1e98a2f815b0 tomcat02:1.1 sha256:cdccd4674f93ad34bf73d9db577a20f027a6d03fd1944dc0e628ee4bf17ec748 [root@kuangshen /]# docker images # 查看,我们自己提交的镜像已经OK了!
REPOSITORY TAG IMAGE ID CREATED 
SIZE tomcat02 1.1 cdccd4674f93 About a minute 
ago 649MB redis latest f9b990972689 9 days ago 
104MB tomcat latest 927899a31456 2 weeks ago 647MB 
centos latest 470671670cac 3 months ago 237MB 

# 4、这个时候,我们的镜像都是可以使用的,大家可以启动原来的tomcat,和我们新的tomcat02来 测试看看! 
[root@kuangshen ~]# docker run -it -p 8080:8080 tomcat02:1.1 
# 如果你想要保存你当前的状态,可以通过commit,来提交镜像,方便使用,类似于 VM 中的快照!

五、容器数据卷

什么是容器数据卷

docker的理念回顾:

将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够

持久化的!

就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!

所以我们希望容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成

新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行

不通的!

为了能保存数据在Docker中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除

而丢失了!

作用:

卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此

能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂

载的数据卷。

特点:

1、数据卷可在容器之间共享或重用数据

2、卷中的更改可以直接生效

3、数据卷中的更改不会包含在镜像的更新中

4、数据卷的生命周期一直持续到没有容器使用它为止

所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

使用数据卷

方式一:容器中直接使用命令来添加

挂载

# 命令 

docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名 

# 测试 

[root@kuangshen ~]# docker run -it -v /home/ceshi:/home centos /bin/bash 

查看数据卷是否挂载成功 docker inspect 容器id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l85JAQQJ-1637315135088)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025111435694.png)]

测试容器和宿主机之间数据共享:可以发现,在容器中,创建的会在宿主机中看到!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SoeUOf5V-1637315135089)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025111503166.png)]

测试容器停止退出后,主机修改数据是否会同步!

  1. 停止容器

  2. 在宿主机上修改文件,增加些内容

  3. 启动刚才停止的容器

  4. 然后查看对应的文件,发现数据依旧同步!ok

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Njxxkbps-1637315135090)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025111545403.png)]

使用 docker 安装 mysql

思考:mysql 数据持久化的问题!

# 1、搜索镜像 
[root@kuangshen ~]# docker search mysql 
NAME DESCRIPTION 
STARS 
mysql  MySQL is a widely used, open-source 
relation… 9488 
# 2、拉取镜像 [root@kuangshen ~]# docker pull mysql:5.7 
5.7: Pulling from library/mysql 
54fec2fa59d0: Already exists 
bcc6c6145912: Pull complete 
951c3d959c9d: Pull complete 
05de4d0e206e: Pull complete 
319f0394ef42: Pull complete 
d9185034607b: Pull complete 
013a9c64dadc: Pull complete 
e745b3361626: Pull complete 
03145d87b451: Pull complete 
3991a6b182ee: Pull complete 
62335de06f7d: Pull complete 

Digest: sha256:e821ca8cc7a44d354486f30c6a193ec6b70a4eed8c8362aeede4e9b8d74b8ebb Status: Downloaded newer image for mysql:5.7 
docker.io/library/mysql:5.7 

# 3、启动容器 -e 环境变量! 
# 注意: mysql的数据应该不丢失!先体验下 -v 挂载卷! 参考官方文档 
[root@kuangshen home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 4763fa5c68c4323688102f57938fb10996a0fb902d2812349286529f9378f16c 

# 4、使用本地的sqlyog连接测试一下 3310 
# 5、查看本地的 /home/mysql 目录 
[root@kuangshen data]# pwd 
/home/mysql/data [root@kuangshen data]# ls 
.. ... . test # 可以看到我们刚刚建立的mysql数据库在本地存储着
# 6、删除mysql容器 
[root@kuangshen data]# docker rm -f mysql01 
# 删除容器,然后发现远程连接失败! mysql01 
[root@kuangshen data]# ls 
.. ... . test # 可以看到我们刚刚建立的mysql数据库在本地存储着

通过Docker File 来添加(了解)

DockerFile 是用来构建Docker镜像的构建文件,是由一些列命令和参数构成的脚本。
我们在这里,先体验下,后面我们会详细讲解 DockerFile !
测试:

# 1、我们在宿主机 /home 目录下新建一个 docker-test-volume文件夹 
[root@kuangshen home]# mkdir docker-test-volume 

# 说明:在编写DockerFile文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷 VOLUME["/dataVolumeContainer1","/dataVolumeContainer2","/dataVolumeContainer 3"] 
# 出于可移植和分享的考虑,我们之前使用的 -v 主机目录:容器目录 这种方式不能够直接在 
DockerFile中实现。 
# 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有宿主机上都存在这样的特定目录. 
# 2、编写DockerFile文件 
[root@kuangshen docker-test-volume]# pwd 
/home/docker-test-volume [root@kuangshen docker-test-volume]# vim dockerfile1 [root@kuangshen docker-test-volume]# cat dockerfile1 
# volume test 
FROM centos 
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"] 
CMD echo "-------end------" 
CMD /bin/bash 

# 3、build后生成镜像,获得一个新镜像 kuangshen/centos
docker build -f /home/docker-test-volume/dockerfile1 -t kuangshen/centos . # 注意最后有个.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k5wudg2U-1637315135091)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025115249488.png)]

# 4、启动容器 
[root@kuangshen docker-test-volume]# docker run -it 0e97e1891a3d /bin/bash 
# 启动容器 
[root@f5824970eefc /]# ls -l 
total 56 
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin 
drwxr-xr-x 2 root root 4096 May 11 11:55 dataVolumeContainer1 # 数据卷目录 
drwxr-xr-x 2 root root 4096 May 11 11:55 dataVolumeContainer2 # 数据卷目录 
drwxr-xr-x 5 root root 360 May 11 11:55 dev 
drwxr-xr-x 1 root root 4096 May 11 11:55 etc 
drwxr-xr-x 2 root root 4096 May 11 2019 home 
..... 

# 问题:通过上述步骤,容器内的卷目录地址就已经知道了,但是对应的主机目录地址在哪里呢? 

# 5、我们在数据卷中新建一个文件 
[root@f5824970eefc dataVolumeContainer1]# pwd 
/dataVolumeContainer1 
[root@f5824970eefc dataVolumeContainer1]# touch container.txt [root@f5824970eefc dataVolumeContainer1]# ls -l 
total 0 
-rw-r--r-- 1 root root 0 May 11 11:58 container.txt 

# 6、查看下这个容器的信息 [root@kuangshen ~]# docker inspect 0e97e1891a3d 
# 查看输出的Volumes 
"Volumes": { "/dataVolumeContainer1": {}, 
"/dataVolumeContainer2": {} 
},

# 7、这个卷在主机对应的默认位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iwEB8zLa-1637315135091)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211025115512368.png)]

注意:如果访问出现了 cannot open directory: Permission denied

解决办法:在挂载目录后多加一个 --privileged=true参数即可

匿名和具名挂载

# 匿名挂载 
-v 容器内路径 docker run -d -P --name nginx01 -v /etc/nginx nginx 
# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护 
docker volume ls 

# 具名挂载 
-v 卷名:/容器内路径 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx 

# 查看挂载的路径 
[root@kuangshen ~]# docker volume inspect nginxconfig
[ 
	{ "CreatedAt": "2020-05-13T17:23:00+08:00", 
	"Driver": "local", 
	"Labels": null, 
	"Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data", 
	"Name": "nginxconfig", 
	"Options": null, 
	"Scope": "local" 
	} 
	]
	
# 怎么判断挂载的是卷名而不是本机目录名? 不
是/开始就是卷名,是/开始就是目录名 
# 改变文件的读写权限 
# ro: readonly 
# rw: readwrite 
# 指定容器对我们挂载出来的内容的读写权限 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

数据卷容器

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

我们使用上一步的镜像:kuangshen/centos 为模板,运行容器 docker01,docker02,docker03,他们都会具有容器卷

"/dataVolumeContainer1" 
"/dataVolumeContainer2"

我们来测试下,容器间传递共享

1、先启动一个父容器docker01,然后在dataVolumeContainer2新增文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OfI5bkI8-1637315135092)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116160301015.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y4h2Wyw6-1637315135093)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116160330359.png)]

退出不停止:ctrl+P+Q

2、创建docker02,docker03 让他们继承docker01 --volumes-from

[root@kuangshen docker-test-volume]# docker run -it --name docker02 -- 
volumes-from docker01 kuangshen/centos 
[root@ea4c82779077 /]# cd /dataVolumeContainer2 
[root@ea4c82779077 dataVolumeContainer2]# ls docker01.txt 
[root@95164598b306 dataVolumeContainer2]# touch docker02.txt 
[root@95164598b306 dataVolumeContainer2]# ls docker01.txt docker02.txt 
[root@kuangshen docker-test-volume]# docker run -it --name docker03 -- volumes-from docker01 kuangshen/centos [root@ea4c82779077 /]# cd /dataVolumeContainer2 
[root@ea4c82779077 dataVolumeContainer2]# ls docker01.txt docker02.txt 
[root@95164598b306 dataVolumeContainer2]# touch docker03.txt 
[root@95164598b306 dataVolumeContainer2]# ls docker01.txt docker02.txt docker03.txt

3、回到docker01发现可以看到 02 和 03 添加的共享文件

[root@kuangshen docker-test-volume]# docker attach docker01 
[root@799b6ea5db7c dataVolumeContainer2]# ls -l 
total 0 
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt 
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt 
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt

4、删除docker01,docker02 修改后docker03还能不能访问

[root@kuangshen docker-test-volume]# docker rm -f docker01 
docker01 
[root@kuangshen docker-test-volume]# docker attach docker02 
[root@ea4c82779077 dataVolumeContainer2]# ls -l 
total 0 
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt 
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt 
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt 
[root@ea4c82779077 dataVolumeContainer2]# touch docker02-update.txt 
[root@ea4c82779077 dataVolumeContainer2]# ls -a 
. .. docker01.txt docker02.txt docker02-update.txt docker03.txt 
[root@ea4c82779077 dataVolumeContainer2]# Ctrl+P+Q 退出容器 


5、删除docker02 ,docker03还能不能访问

5、删除docker02 ,docker03还能不能访问
[root@kuangshen docker-test-volume]# docker ps 
CONTAINER ID IMAGE 
95164598b306 kuangshen/centos 
ea4c82779077 kuangshen/centos 
[root@kuangshen docker-test-volume]# docker rm -f docker02 
docker02 
[root@kuangshen docker-test-volume]# docker attach docker03 
[root@95164598b306 dataVolumeContainer2]# ls -l 
total 0 
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt 
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt 
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt 
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt 
[root@95164598b306 dataVolumeContainer2]# touch docker03-update.txt

6、新建docker04继承docker03,然后再删除docker03,看下是否可以访问!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AtPwBu8n-1637315135094)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116161123695.png)]

[root@2119f4f23a92 /]# cd dataVolumeContainer2 
[root@2119f4f23a92 dataVolumeContainer2]# ls -l 
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt 
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt 
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt 
-rw-r--r-- 1 root root 0 May 11 13:32 docker03-update.txt 
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt 

# 查看当前运行的容器 [root@kuangshen docker-test-volume]# docker ps 
CONTAINER ID IMAGE NAMES 
2119f4f23a92 kuangshen/centos docker04 
95164598b306 kuangshen/centos docker03 

# 继续删除docker03 [root@kuangshen docker-test-volume]# docker rm -f docker03 
docker03 
[root@kuangshen docker-test-volume]# docker attach docker04 
[root@2119f4f23a92 dataVolumeContainer2]# ls -l 
total 0 
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt 
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt 
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt 
-rw-r--r-- 1 root root 0 May 11 13:32 docker03-update.txt 
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt

得出结论:

容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

存储在本机的文件则会一直保留!

六、DockerFile

大家想想,Nginx,tomcat,mysql 这些镜像都是哪里来的?官方能写,我们不能写吗?

我们要研究自己如何做一个镜像,而且我们写的微服务项目以及springboot打包上云部署,Docker就是

最方便的。

微服务打包成镜像,任何装了Docker的地方,都可以下载使用,极其的方便。

流程:开发应用=>DockerFile=>打包为镜像=>上传到仓库(私有仓库,公有仓库)=> 下载镜像 => 启动

运行。

还可以方便移植!

什么是DockerFile

dockerfifile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

构建步骤:

1、编写DockerFile文件

2、docker build 构建镜像

3、docker run

dockerfifile文件我们刚才已经编写过了一次,这里我们继续使用 centos 来看!

地址:https://hub.docker.com/_/centos

image-20211116161719762 image-20211116161754255

DockerFile构建过程

基础知识:

1、每条保留字指令都必须为大写字母且后面要跟随至少一个参数

2、指令按照从上到下,顺序执行

3、# 表示注释

4、每条指令都会创建一个新的镜像层,并对镜像进行提交

流程:

1、docker从基础镜像运行一个容器

2、执行一条指令并对容器做出修改

3、执行类似 docker commit 的操作提交一个新的镜像层

4、Docker再基于刚提交的镜像运行一个新容器

5、执行dockerfifile中的下一条指令直到所有指令都执行完成!

说明:

从应用软件的角度来看,DockerFile,docker镜像与docker容器分别代表软件的三个不同阶段。

DockerFile 是软件的原材料 (代码)

Docker 镜像则是软件的交付品 (.apk)

Docker 容器则是软件的运行状态 (客户下载安装执行)

DockerFile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PhxFXaia-1637315135095)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116162102854.png)]

DockerFile:需要定义一个DockerFile,DockerFile定义了进程需要的一切东西。DockerFile涉及的内容

包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进

程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权

限控制)等等。

Docker镜像:在DockerFile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行

Docker 镜像时,会真正开始提供服务;

Docker容器:容器是直接提供服务的。

DockerFile指令

FROM # 基础镜像,当前新镜像是基于哪个镜像的 
MAINTAINER # 镜像维护者的姓名混合邮箱地址 
RUN # 容器构建时需要运行的命令 
EXPOSE # 当前容器对外保留出的端口 
WORKDIR # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点 
ENV # 用来在构建镜像过程中设置环境变量 
ADD # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 
COPY # 类似ADD,拷贝文件和目录到镜像中! 
VOLUME # 容器数据卷,用于数据保存和持久化工作 
CMD # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最 后一个生效!
ENTRYPOINT # 指定一个容器启动时要运行的命令!和CMD一样 
ONBUILD # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD被触发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHVELjN3-1637315135096)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116163059438.png)]

实战测试

Docker Hub 中99% 的镜像都是通过在base镜像(Scratch)中安装和配置需要的软件构建出来的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HLIMJGLz-1637315135097)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116163536562.png)]

自定义一个 centos

1、编写DockerFile

查看下官方默认的CentOS的情况:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JjYG8pja-1637315135098)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116164623872.png)]

目的:使我们自己的镜像具备如下:登陆后的默认路径、vim编辑器、查看网络配置ifconfifig支持

准备编写DockerFlie文件

[root@kuangshen home]# mkdir dockerfile-test 
[root@kuangshen home]# ls ceshi dockerfile-test docker-test-volume f1 
[root@kuangshen home]# 
[root@kuangshen home]# vim mydockerfile-centos # 编辑文件 
[root@kuangshen home]# cat mydockerfile-centos 
FROM centos 
MAINTAINER kuangshen<24736743@qq.com> 


ENV MYPATH /usr/local WORKDIR $MYPATH 
RUN yum -y install vim 
RUN yum -y install net-tools 4
EXPOSE 80 
CMD echo $MYPATH 
CMD echo "----------end--------" 
CMD /bin/bash

2、构建

docker build -f dockerfile地址 -t 新镜像名字:TAG .

会看到 docker build 命令最后有一个 . . 表示当前目录

[root@kuangshen home]# docker build -f mydockerfile-centos -t mycentos:0.1 .

【详见Pdf文件】

3、运行

docker run -it 新镜像名字:TAG

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2GZisdGd-1637315135099)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116165842705.png)]

可以看到,我们自己的新镜像已经支持 vim/ifconfifig的命令,扩展OK!

4、列出镜像地的变更历史

docker history 镜像名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H6T4m06L-1637315135100)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116165934843.png)]

CMD 和 ENTRYPOINT 的区别

我们之前说过,两个命令都是指定一个容器启动时要运行的命令

CMD:Dockerfifile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数

替换!

ENTRYPOINT:docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

测试:

CMD命令

# 1、构建dockerfile 
[root@kuangshen home]# vim dockerfile-cmd-test 
[root@kuangshen home]# cat dockerfile-cmd-test 
FROM centos 
CMD [ "ls", "-a" ] 

# 2、build 镜像 [root@kuangshen home]# docker build -f dockerfile-cmd-test -t cmdtest . 
Sending build context to Docker daemon 22.02kB 
Step 1/2 : FROM centos 
---> 470671670cac Step 2/2 : CMD [ "ls", "-a" ] 
---> Running in a3072987de38 
Removing intermediate container a3072987de38 
---> 554bc6952657 S
uccessfully built 554bc6952657 
Successfully tagged cmdtest:latest 

# 3、执行 [root@kuangshen home]# docker run 554bc6952657 
.dockerenv 
bin 
dev 
etc 
home 
lib 
lib64 
...... 

# 4、如果我们希望用 -l 列表展示信息,我们就需要加上 -l参数 
[root@kuangshen home]# docker run cmdtest -l 
docker: Error response from daemon: OCI runtime create failed: 
container_linux.go:349: starting container process caused "exec: \"-l\": 
executable file not found in $PATH": unknown.

# 问题:我们可以看到可执行文件找不到的报错,executable file not found。 
# 之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。 
# 因此这里的 -l 替换了原来的 CMD,而不是添加在原来的 ls -a 后面。而 -l 根本不是命令,所 以自然找不到。 
# 那么如果我们希望加入 -l 这参数,我们就必须重新完整的输入这个命令: 

docker run cmdtest ls -al

ENTRYPOINT命令

# 1、构建dockerfile 
[root@kuangshen home]# vim dockerfile-entrypoint-test 
[root@kuangshen home]# cat dockerfile-entrypoint-test 
FROM centos 
ENTRYPOINT [ "ls", "-a" ] 

# 2、build 镜像 
[root@kuangshen home]# docker build -f dockerfile-entrypoint-test -t entrypointtest . 
Sending build context to Docker daemon 23.04kB 
Step 1/2 : FROM centos 
---> 470671670cac 
Step 2/2 : ENTRYPOINT [ "ls", "-a" ] 
---> Running in bac4ae055630 
Removing intermediate container bac4ae055630 
---> ae07199f9144 
Successfully built ae07199f9144 
Successfully tagged entrypointtest:latest 

# 3、执行 [root@kuangshen home]# docker run ae07199f9144
.dockerenv 
bin 
dev 
etc 
home 
lib 
lib64 
...... 

# 4、测试-l参数,发现可以直接使用,这里就是一种追加,我们可以明显的知道 CMD 和 ENTRYPOINT 的区别了 
[root@kuangshen home]# docker run entrypointtest -l 
total 56 
drwxr-xr-x 1 root root 4096 May 12 04:21 . 
drwxr-xr-x 1 root root 4096 May 12 04:21
-rwxr-xr-x 1 root root 0 May 12 04:21 .dockerenv 
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin 
drwxr-xr-x 5 root root 340 May 12 04:21 dev 
drwxr-xr-x 1 root root 4096 May 12 04:21 etc 
drwxr-xr-x 2 root root 4096 May 11 2019 home .....

自定义镜像 tomcat

1、 mkdir -p kuangshen/build/tomcat

2、在上述目录下 touch read.txt

3、将 JDK 和 tomcat 安装的压缩包拷贝进上一步目录

4、在 /kuangshen/build/tomcat 目录下新建一个Dockerfifile文件

# vim Dockerfile 

FROM centos 
MAINTAINER kuangshen<24736743@qq.com> 
#把宿主机当前上下文的read.txt拷贝到容器/usr/local/路径下 
COPY read.txt /usr/local/cincontainer.txt 
#把java与tomcat添加到容器中 
ADD jdk-8u11-linux-x64.tar.gz /usr/local/ 
ADD apache-tomcat-9.0.22.tar.gz /usr/local/ 
#安装vim编辑器 
RUN yum -y install vim 
#设置工作访问时候的WORKDIR路径,登录落脚点 
ENV MYPATH /usr/local WORKDIR $MYPATH 
#配置java与tomcat环境变量 
ENV JAVA_HOME /usr/local/jdk1.8.0_11 
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22 
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.22 
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin 
#容器运行时监听的端口 
EXPOSE 8080 
#启动时运行tomcat 
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.22/bin/startup.sh" ] 
# CMD ["/usr/local/apache-tomcat-9.0.22/bin/catalina.sh","run"] 
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F 
/usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out

当前文件状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUZmqYaM-1637315135101)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116171515314.png)]

5、构建镜像

[root@kuangshen tomcat]# docker build -t diytomcat . 
..... 
Successfully built ffdf6529937d 
Successfully tagged diytomcat:latest # 构建完成 

# 查看确定构建完毕! 
[root@kuangshen tomcat]# docker images 
REPOSITORY  TAG  IMAGE ID       CREATED 
SIZE 
diytomcat  latest  ffdf6529937d  20 seconds ago 
636MB

6、运行启动 run

docker run -d -p 9090:8080 --name mydiytomcat -v 
/home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat- 
9.0.22/webapps/test -v 
/home/kuangshen/build/tomcat/tomcat9logs/:/usr/local/apache-tomcat- 
9.0.22/logs --privileged=true diytomcat

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-trQAcrqY-1637315135102)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116171622068.png)]

备注:Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied

解决办法:在挂载目录后多加一个–privileged=true参数即可

7、验证测试访问! curl localhost:9090

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EhBA7DdN-1637315135102)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116171701594.png)]

8、结合前面学习的容器卷将测试的web服务test发布

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dOKIymJ2-1637315135104)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116171728569.png)]

web.xml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uuOPwMpg-1637315135104)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116173443124.png)]

a.jsp

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xBlLCGAg-1637315135114)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116173510837.png)]

9、测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tR5TrLdm-1637315135116)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116173531986.png)]

# 查看日志 [root@kuangshen tomcat]# cd tomcat9logs/ 
[root@kuangshen tomcat9logs]# ll 
total 24 -rw-r----- 1 root root 6993 May 12 12:50 catalina.2020-05-12.log 
-rw-r----- 1 root root 7024 May 12 12:53 catalina.out
-rw-r----- 1 root root 0 May 12 12:47 host-manager.2020-05-12.log 
-rw-r----- 1 root root 408 May 12 12:47 localhost.2020-05-12.log 
-rw-r----- 1 root root 150 May 12 12:53 localhost_access_log.2020-05-12.txt 
-rw-r----- 1 root root 0 May 12 12:47 manager.2020-05-12.log 
[root@kuangshen tomcat9logs]# cat catalina.out 
.... 
-------my docker tomcat------- # 搞定

发布镜像

DockerHub

注册dockerhub https://hub.docker.com/signup,需要有一个账号

# 1、查看登录命令 
[root@kuangshen tomcat]# docker login --help 
Usage: docker login [OPTIONS] [SERVER] 
# 2、登录 
[root@kuangshen tomcat]# docker login -u kuangshen 
Password: 
WARNING! Your password will be stored unencrypted in 
/root/.docker/config.json.
Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials- store 
Login Succeeded 
# 3、将镜像发布出去 
[root@kuangshen tomcat]# docker push kuangshen/diytomcat:1.0 T
he push refers to repository [docker.io/library/diytomcat] 
0f02399c6fdf: Preparing 
e79ea0c3a34e: Preparing 
09281fa8fe38: Preparing 
b56a902b0aef: Preparing 
0683de282177: Preparing 
# 拒绝:请求的资源访问被拒绝 
denied: requested access to the resource is denied 

# 问题:本地镜像名无帐号信息,解决加 tag即可 
docker tag 251ca4419332 kuangshen/diytomcat:1.0 

# 再次 push, ok 
[root@kuangshen tomcat]# docker push kuangshen/diytomcat:1.0 
The push refers to repository [docker.io/kuangshen/diytomcat] 
0f02399c6fdf: Pushing [========>                      ] 
9.729MB/59.76MB 
e79ea0c3a34e: Pushing [==========>                     ]
3.188MB/15.41MB 09281fa8fe38: Pushing [>                   ]
3.823MB/324MB 
b56a902b0aef: Pushed 
0683de282177: Pushing [=>                                   ]
5.997MB/237.1MB

阿里云镜像服务

1、登录阿里云

2、找到容器镜像服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0rj4PK9A-1637315135117)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174235351.png)]

3、创建命名空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HMfvkkAK-1637315135117)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174252856.png)]

4、创建镜像仓库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCqjeQGn-1637315135118)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174325452.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6swnCslR-1637315135119)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174349828.png)]

5、点击进入这个镜像仓库,可以看到所有的信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HmTCnLne-1637315135120)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174417742.png)]

6、测试推送发布

# 1、登录阿里云 
[root@kuangshen tomcat]# docker login --username=18225148644 registry.cn- 
beijing.aliyuncs.com
Password: WARNING! Your password will be stored unencrypted in 
/root/.docker/config.json. 
Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials- 
store 

Login Succeeded 

# 2、设置 tag d
ocker tag [ImageId] registry.cn-beijing.aliyuncs.com/bilibili- 
kuangshen/kuangshen-test:[镜像版本号] 
[root@kuangshen tomcat]# docker tag 251ca4419332 registry.cn- 
beijing.aliyuncs.com/bilibili-kuangshen/kuangshen-test:v1.0 

# 3、推送命令 docker push registry.cn-beijing.aliyuncs.com/bilibili-kuangshen/kuangshen- 
test:[镜像版本号] 
[root@kuangshen tomcat]# docker push registry.cn- 
beijing.aliyuncs.com/bilibili-kuangshen/kuangshen-test:v1.0

7、在阿里云镜像仓库查看效果!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zqg5akVz-1637315135121)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174629261.png)]

总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ET2MDhOp-1637315135121)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116174736061.png)]

七、Docker 网络讲解

理解Docker0

准备工作:清空所有的容器,清空所有的镜像

docker rm -f $(docker ps -a -q) # 删除所有容器 
docker rmi -f $(docker images -qa) # 删除全部镜像

Docker的网络也是十分重要的一个点,希望大家可以认真理解!

我们先来做个测试

查看本地ip >ip addr

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KcRF72ZG-1637315135122)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116175005639.png)]

这里我们分析可得,有三个网络:

lo 127.0.0.1 # 本机回环地址 
eth0 172.17.90.138 # 阿里云的私有IP 
docker0 172.18.0.1 # docker网桥 
# 问题:Docker 是如何处理容器网络访问的?

我们之前安装ES的时候,留过一个问题,就是安装Kibana的问题,Kibana得指定ES的地址!或者我们

实际场景中,我们开发了很多微服务项目,那些微服务项目都要连接数据库,需要指定数据库的url地

址,通过ip。但是我们用Docker管理的话,假设数据库出问题了,我们重新启动运行一个,这个时候数

据库的地址就会发生变化,docker会给每个容器都分配一个ip,且容器和容器之间是可以互相访问的。

我们可以测试下容器之间能不能ping通过:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2iZ96nim-1637315135123)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116175209152.png)]

原理

1、每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair

技术

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JioH2FL7-1637315135123)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116175259403.png)]

2、每启动一个容器,linux主机就会多了一个虚拟网卡。

# 我们启动了一个tomcat01,主机的ip地址多了一个 123: vethc8584ea@if122 
# 然后我们在tomcat01容器中查看容器的ip是 122: eth0@if123 

# 我们再启动一个tomcat02观察 
[root@kuangshen ~]# docker run -d -P --name tomcat02 tomcat 

# 然后发现linux主机上又多了一个网卡 125: veth021eeea@if124: 
# 我们看下tomcat02的容器内ip地址是 124: eth0@if125: 
[root@kuangshen ~]# docker exec -it tomcat02 ip addr

# 观察现象: # tomcat --- linux主机 vethc8584ea@if122 ---- 容器内 eth0@if123 
# tomcat --- linux主机 veth021eeea@if124 ---- 容器内 eth0@if125 
# 相信到了这里,大家应该能看出点小猫腻了吧!只要启动一个容器,就有一对网卡 

# veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。
# 正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备! 
# “Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络
结构,比如 OpenStack Neutron。

3、我们来测试下tomcat01和tomcat02容器间是否可以互相ping通

[root@kuangshen ~]# docker exec -it tomcat02 ping 172.18.0.2 
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data. 
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.110 ms 

# 结论:容器和容器之间是可以互相访问的。

4、我们来画一个网络模型图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7pVHywaE-1637315135124)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211116180200312.png)]

结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动

默认都是docker0网络。

docker默认会给容器分配一个可用ip。

小结

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHzv213Z-1637315135125)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117105918433.png)]

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

–Link

思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们能不能使用服务名访问呢?

jdbc:mysql://mysql:3306,这样的话哪怕mysql重启,我们也不需要修改配置了!docker提供了 --link的操作!

# 我们使用tomcat02,直接通过容器名ping tomcat01,不使用ip 
[root@kuangshen ~]# docker exec -it tomcat02 ping tomcat01 
ping: tomcat01: Name or service not known # 发现ping不通 

# 我们再启动一个tomcat03,但是启动的时候连接tomcat02 
[root@kuangshen ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat a3a4a17a2b707766ad4f2bb967ce1d94f658cd4cccef3bb8707395cdc71fa1e7 

# 这个时候,我们就可以使用tomcat03 ping通tomcat02 了
[root@kuangshen ~]# docker exec -it tomcat03 ping tomcat02 
PING tomcat02 (172.18.0.3) 56(84) bytes of data. 64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.093 ms 64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.066 ms 

# 再来测试,tomcat03 是否可以ping tomcat01 失败 
[root@kuangshen ~]# docker exec -it tomcat03 
ping tomcat01 ping: tomcat01: Name or service not known 
# 再来测试,tomcat02 是否可以ping tomcat03 反向也ping不通 
[root@kuangshen ~]# docker exec -it tomcat02 ping tomcat03 
ping: tomcat03: Name or service not known 

思考,这个原理是什么呢?我们进入tomcat03中查看下host配置文件

[root@kuangshen ~]# docker exec -it tomcat03 cat /etc/hosts 
127.0.0.1 localhost ::1 localhost 
ip6-localhost ip6-loopback
fe00::0 ip6-localnet 
ff00::0 ip6-mcastprefix 
ff02::1 ip6-allnodes 
ff02::2 ip6-allrouters 
172.18.0.3 tomcat02 b80da266a3ad # 发现tomcat2直接被写在这里 
172.18.0.4 a3a4a17a2b70 

# 所以这里其实就是配置了一个 hosts 地址而已!
# 原因:--link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中了。

–link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式

自定义网络

基本命令查看

命令如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mjHs13nO-1637315135125)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117110438447.png)]

查看所有网络

[root@kuangshen ~]# docker network ls 
NETWORK ID NAME DRIVER SCOPE 
4eb2182ac4b2 bridge bridge local 
ae2b6209c2ab host host local 
c037f7ec7e57 none null local

所有网路模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hRS70jl3-1637315135126)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117110546075.png)]

查看一个具体的网络的详细信息

# 命令 
[root@kuangshen ~]# docker network inspect 4eb2182ac4b2
...... []

自定义网卡

1、删除原来的所有容器

[root@kuangshen ~]# docker rm -f $(docker ps -aq) 

# 恢复到了最开始的样子 
[root@kuangshen ~]# ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 
	link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 
	inet 127.0.0.1/8 scope host lo 
		valid_lft forever preferred_lft forever 12345678
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state 
UP group default qlen 1000 
	link/ether 00:16:3e:30:27:f4 brd ff:ff:ff:ff:ff:ff 
		inet 172.17.90.138/20 brd 172.17.95.255 scope global dynamic eth0 				valid_lft 310951436sec preferred_lft 310951436sec 
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
	link/ether 02:42:bb:71:07:06 brd ff:ff:ff:ff:ff:ff 
	inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0 
		valid_lft forever preferred_lft forever

2、接下来我们来创建容器,但是我们知道默认创建的容器都是docker0网卡的

# 默认我们不配置网络,也就相当于默认值 --net bridge 使用的docker0 
docker run -d -P --name tomcat01 --net bridge tomcat

# docker0网络的特点
1.它是默认的 
2.域名访问不通 
3.--link 域名通了,但是删了又不行

3、我们可以让容器创建的时候使用自定义网络

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dxkqu9kP-1637315135127)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117111030418.png)]

# 自定义创建的默认default "bridge" 
# 自定义创建一个网络网络 
[root@kuangshen ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236 

# 确认下 
[root@kuangshen ~]# docker network ls 
NETWORK ID NAME DRIVER SCOPE 
4eb2182ac4b2 bridge bridge local 
ae2b6209c2ab host host local 
09bd09d8d3a6 mynet bridge local 
c037f7ec7e57 none null local
[root@kuangshen ~]# docker network inspect mynet 
[ { "Name": "mynet", "Id": "09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236", 
"Created": "2020-05-13T13:29:33.568644836+08:00", 
"Scope": "local", 
"Driver": "bridge", 
"EnableIPv6": false, 
"IPAM": { 
"Driver": "default", 
"Options": {}, 
"Config": [ 
{ 
"Subnet": "192.168.0.0/16", 
"Gateway": "192.168.0.1" 
} 
] 
},
"Internal": false,
"Attachable": false, 
"Ingress": false, 
"ConfigFrom": 
{ "Network": "" 
},
"ConfigOnly": false, 
"Containers": {}, 
"Options": {}, 
"Labels": {} 
} 
]
# 我们来启动两个容器测试,使用自己的 mynet! 
[root@kuangshen ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat 065f82e947c760c63539ab4c0de0d683787ec7ac6d0dcaa71f64e191319f9fe7 [root@kuangshen ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat 2e85d71afe87c87166786b0bbae2d90eefb969d716fcd78a21173add5956cb12 [root@kuangshen ~]# docker ps 
CONTAINER ID IMAGE PORTS NAMES 2e85d71afe87 tomcat 0.0.0.0:32772->8080/tcp tomcat-net-02 065f82e947c7 tomcat 0.0.0.0:32771->8080/tcp tomcat-net-01 

# 再来查看下 [root@kuangshen ~]# docker network inspect mynet 
[ { "Name": "mynet", 
"Id": 
"09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236", ............ 
"Containers": { 

"065f82e947c760c63539ab4c0de0d683787ec7ac6d0dcaa71f64e191319f9fe7": { 
"Name": "tomcat-net-01",
"EndpointID": "d61cef1bc294d7f10fb6d9b728735fc87bed79e4e02f5298374f0fab3e9b2da6", "MacAddress": "02:42:c0:a8:00:02", 
"IPv4Address": "192.168.0.2/16", 
"IPv6Address": "" 
}, 

"2e85d71afe87c87166786b0bbae2d90eefb969d716fcd78a21173add5956cb12": { 
"Name": "tomcat-net-02", 
"EndpointID": "adbc37a20526c2985c3589382998a3d106ef722662c7b296a57d8a7c8f449f38", "MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16", 
"IPv6Address": "" 
} 
},
"Options": {},
"Labels": {} 
} 
]

# 我们来测试ping容器名和ip试试,都可以ping通 
[root@kuangshen ~]# docker exec -it tomcat-net-01 ping 192.168.0.3 
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data. 64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.093 ms 
[root@kuangshen ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.063 ms 
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.066 ms 
# 发现,我们自定义的网络docker都已经帮我们维护好了对应的关系 
# 所以我们平时都可以这样使用网络,不使用--link效果一样,所有东西实时维护好,直接域名 ping 通。

聊了这么多,我们现在应该可以深刻理解docker的网络了!

网络连通

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbfRecoW-1637315135127)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117111607127.png)]

docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离:

大家公司项目部署的业务都非常多,假设我们有一个商城,我们会有订单业务(操作不同数据),会有订单业务购物车业务(操作不同缓存)。如果在一个网络下,有的程序猿的恶意代码就不能防止了,所以我们就在部署的时候网络隔离,创建两个桥接网卡,比如订单业务(里面的数据库,redis,mq,全部业务 都在order-net网络下)其他业务在其他网络。

那关键的问题来了,如何让 tomcat-net-01 访问 tomcat1?

# 查看当前的容器 
[root@kuangshen ~]# docker ps
CONTAINER ID IMAGE PORTS NAMES 
6183aaeca003 tomcat 0.0.0.0:32774->8080/tcp tomcat02 
bcd122e0dcf6 tomcat 0.0.0.0:32773->8080/tcp tomcat01 
2e85d71afe87 tomcat 0.0.0.0:32772->8080/tcp tomcat- net-02 
065f82e947c7 tomcat 0.0.0.0:32771->8080/tcp tomcat- net-01 

#我们来查看下network帮助,发现一个命令 connect 
[root@kuangshen ~]# docker network --help 
Commands: 
connect Connect a container to a network # 连接一个容器到一个网络
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks 
ls List networks 
prune Remove all unused networks 
rm Remove one or more networks 

# 我们来测试一下!打通mynet-docker0 
# 命令 docker network connect [OPTIONS] NETWORK CONTAINER 

[root@kuangshen ~]# docker network connect mynet tomcat01 
[root@kuangshen ~]# docker network inspect mynet 
[ {
...... 
"Containers": { "065f82e947c760c63539ab4c0de0d683787ec7ac6d0dcaa71f64e191319f9fe7": {
"Name": "tomcat-net-01", 
"EndpointID": "d61cef1bc294d7f10fb6d9b728735fc87bed79e4e02f5298374f0fab3e9b2da6", "MacAddress": "02:42:c0:a8:00:02", 
"IPv4Address": "192.168.0.2/16", 
"IPv6Address": "" 
},

"2e85d71afe87c87166786b0bbae2d90eefb969d716fcd78a21173add5956cb12": { 
"Name": "tomcat-net-02", 
"EndpointID": "adbc37a20526c2985c3589382998a3d106ef722662c7b296a57d8a7c8f449f38", "MacAddress": "02:42:c0:a8:00:03", 
"IPv4Address": "192.168.0.3/16",
"IPv6Address": "" 
},
// 发现我们的tomcat01就进来这里了,tomcat01拥有了双ip

"bcd122e0dcf6bf8c861eaa934911f98a5497a4954f3fde9575e496160bd23287": {
"Name": "tomcat01",
"EndpointID": "b2bf2342948e17048d872a4d5603c77e90d0e032439d510e86c10a1acc3928d9", "MacAddress": "02:42:c0:a8:00:04", 
"IPv4Address": "192.168.0.4/16", 
"IPv6Address": "" 
} 
},
...... 
} 
]

# tomcat01 可以ping通了 
[root@kuangshen ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data. 
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.071 ms 
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.067 ms 
# tomcat02 依旧ping不通,大家应该就理解了
[root@kuangshen ~]# docker exec -it tomcat02 ping tomcat-net-01 
ping: tomcat-net-01: Name or service not known

结论:如果要跨网络操作别人,就需要使用 docker network connect [OPTIONS] NETWORK

CONTAINER 连接

实战:部署一个Redis集群

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RrcD2UFF-1637315135128)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117112206633.png)]

# 创建网卡 docker network create redis --subnet 172.38.0.0/16 

# 通过脚本创建六个redis配置
for port in $(seq 1 6); \ 
do \ 
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf 
port 6379 
bind 0.0.0.0 
cluster-enabled yes 
cluster-config-file nodes.conf 
cluster-node-timeout 5000 
cluster-announce-ip 172.38.0.1${port} 
cluster-announce-port 6379 
cluster-announce-bus-port 16379 
appendonly yes 
EOF 
done 
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \ 
-v /mydata/redis/node-${port}/data:/data \ 
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \ 
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

# 启动6个容器 
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ 
-v /mydata/redis/node-1/data:/data \ 
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ 
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf 

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ 
-v /mydata/redis/node-6/data:/data \ 
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ 
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

# 进入一个redis,注意这里是 sh命令 
docker exec -it redis-1 /bin/sh 

# 创建集群 redis-cli --cluster create 172.38.0.11:6379 
172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 -- 
cluster-replicas 1 

# 连接集群 
redis-cli -c 

# 查看集群信息 
cluster info 

# 查看节点 
cluster nodes 

# set a b 
# 停止到存值的容器 
# 然后再次get a,发现依旧可以获取值 
# 查看节点,发现高可用完全没问题

八、IDEA整合Docker

创建项目

1、使用 IDEA 构建一个 SpringBoot 项目

2、编写一个helloController

@RestController 
public class HelloController { 

@GetMapping("/hello") 
public String hello()
{ 
return "hello,kuangshen"; 
} 
}

3、启动测试下,端口修改下,避免8080冲突!本地访问没问题就可以!

4、打jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9YPZDrCW-1637315135129)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117112931891.png)]

有了 jar 包,我们就可以作镜像了! 记得测试一下jar包可以使用吗!

打包镜像

1、在项目下编写 Dockerfifile 文件,将打包好的jar包拷贝到Dockerfifile同级目录

FROM java:8 
# 服务器只有dockerfile和jar在同级目录 
COPY *.jar /app.jar 
CMD ["--server.port=8080"] 
# 指定容器内要暴露的端口 EXPOSE 8080 
ENTRYPOINT ["java","-jar","/app.jar"]

2、将Dockerfifile 和 项目的 jar 包上传到linux服务器上,构建运行

[root@kuangshen idea]# pwd 
/home/idea [root@kuangshen idea]# ll 
total 17228 -rw-r--r-- 1 root root 17634294 May 14 12:33 demo-0.0.1-SNAPSHOT.jar -rw-r--r-- 1 root root 207 May 14 12:32 Dockerfile 

# 构建镜像 
docker build -t idea-ks . 

# 查看镜像 
docker images 
# 运行 
docker run -d -P --name idea-ks idea-ks 

[root@kuangshen ~]# docker ps 
CONTAINER ID IMAGE PORTS NAMES 
2366c960ba99 idea-ks 0.0.0.0:32779->8080/tcp idea-ks1

# 测试访问 [root@kuangshen ~]# curl localhost:32779 
[root@kuangshen ~]# curl localhost:32779/hello

IDEA安装插件

了解即可!以后CI/CD,就完全没必要这样做!

1、IDEA安装插件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6mLeRGH-1637315135129)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117113318317.png)]

2、配置docker连接集成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SGjItan6-1637315135130)(C:\Users\thtf\AppData\Roaming\Typora\typora-user-images\image-20211117113339577.png)]

3、集成了docker插件就可以在IDEA中操作Docker内部的容器和镜像了,但是很鸡肋这个功能,对于我们开发人员来说!

之后学习的CI/CD才是真正在企业中的王道!

你可能感兴趣的:(docker,容器,运维)