Docker容器

1、Docker概述
文档:https://docs.docker.com/get-started/overview/

为什么会出现
之前开发一款产品:
- 开发–上线,两套环境!应用环境!应用配置!
- 问题:我在我的电脑上可以运行,换个环境却不行!版本更新,导致服务不可用!
- 环境配置十分麻烦,每一个机器都要部署环境(集群Redis、ES、Hadoop……)
- 发布一个项目jar(需要部署Redis、MySQL、jdk、ES)
- 之前在服务器配置应用环境,配置麻烦,不能跨平台
- 开发做jar,运维配置环境!
现在:
- 项目带上环境安装打包
- 开发打包部署上线,一套流程做完
- java – apk – 发布(应用商店) – 下载安装即可用
- java – jar(环境) – 打包项目带上环境(镜像) – Docker仓库:商店 – 下载我们发布的镜像 – 直接运行即可
Docker给以上问题,提供了解决方案!
Docker的思想就来自于集装箱!
之前:Jre – 多个应用(端口冲突) – 原来是交叉的!
隔离:Docker核心思想!打包装箱!每个箱子相互隔离!
Docker通过隔离机制,可以将服务器利用到极致!
Docker的优势
虚拟机:在window中安装一个VMware,通过这个软件我们可以虚拟出一台或者多台电脑!但是笨重!
虚拟机也属于虚拟化技术,但是占用内存大!
Docker:隔离,镜像(最核心的环境 + jdk + mysql)十分小巧,运行镜像就可以,几个M或者KB,秒级启动!
Docker 基于Go语言开发!开源项目!
Docker能干嘛
之前的虚拟机技术

缺点:
- 资源占用多
- 冗余步骤多
- 启动很慢
容器化技术
容器化技术不是模拟的一个完整的操作系统

比较Docker 和 虚拟机技术的不同:
- 传统虚拟机,虚拟一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器中的应用直接运行在 宿主机 的内容,容器时没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间时相互隔离的,每个容器内都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
应用更快速的交付和部署
- 传统:一堆帮助文档,安装程序
- Docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
- 使用了Docker之后,我们部署应用就和搭积木一样
- 项目打包为镜像,扩展 只需要在另一个服务器中一键运行
更简单的系统运维
- 在容器化之后,我们的开发,测试环境都是高度一致的
更高效的计算资源利用
- 可以将服务器的性能应用到极致
- Docker 是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例
2、Docker安装
Docker的基本组成

镜像(image):
- docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
容器(container):
- Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的
- 启动,停止,删除,基本命令
- 目前就可以把这个容器理解为就是一个简易的Linux系统
仓库(repository):
- 仓库就是存放镜像的地方!
- 仓库分为共有仓库和私有仓库!
- Docker Hub(默认是国外的)
- 阿里云…都有容器服务(配置镜像加速)
安装Docker
环境准备
- 需要Linux基础
- CentOS 7
- 使用Xshell连接远程服务器
环境查看
# 查看系统内核版本,需要3.10以上
[root@iz2ze2js0u6m077omgcbzmz /]# uname -r
3.10.0-1127.19.1.el7.x86_64
# 系统配置
[root@iz2ze2js0u6m077omgcbzmz /]# 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"
安装
帮助文档:https://docs.docker.com/get-docker/
需要选择Linux系统的版本

然后选择CentOS版本

步骤:
# 1、卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2、需要的安装包
yum install -y yum-utils
# 3、设置镜像的仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo # 默认是从国外的(太慢,不建议)
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推荐使用阿里云的
# 4、更新软件包索引
yum makecache fast
# 5、安装docker相关的内容,docker-ce 社区版,ee 企业版
yum install docker-ce docker-ce-cli containerd.io
# 6、启动docker
systemctl start docker
# 7、查看是否安装成功
docker version

# 8、使用run启动hello-word镜像
docker run hello-world

# 9、查看一下下载的hello-world镜像是否存在
[root@iz2ze2js0u6m077omgcbzmz /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 13 months ago 13.3kB
卸载docker:
# 1、卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2、删除资源
rm -rf /var/lib/docker # docker的默认工作路径
阿里云镜像加速
1、访问阿里云控制台,找到容器镜像服务

2、点击开通,设置仓库登录密码即可

3、找到镜像加速地址

4、配置使用
# 创建目录
sudo mkdir -p /etc/docker
# 编写配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://keywishf.mirror.aliyuncs.com"]
}
EOF
# 服务重启
sudo systemctl daemon-reload
# 启动doceker
sudo systemctl restart docker
回顾HelloWord流程

底层原理
Docker是怎么工作的?
- Docker 是一个 client - Server 结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!
- DockerServer 接收到 Docker-client 的指令,就会执行这个命令!

Docker为什么比 VM(虚拟机)快?
- Docker有着比虚拟机更少的抽象层
- Docker利用的是宿主机的内核,vm需要的是 Guest OS

所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机加载 Guest OS,分钟级别的,而docker 是利用 宿主机的操作系统,省略了这个复杂的过程,秒级启动!

3、Docker的常用命令
帮助命令
docker version # 像是docker的版本信息
docker info # docker系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
帮助文档地址:https://docs.docker.com/reference/

镜像的命令
docker images :查看本地所有镜像
# 查看镜像
[root@iz2ze2js0u6m077omgcbzmz /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 13 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 常用的可选项
-a, --all # 列出所有的镜像
-q, --quiet # 只显示镜像的id
Docker search 搜索镜像
可以直接在官网搜索镜像:https://hub.docker.com/


使用命令的方式:
[root@iz2ze2js0u6m077omgcbzmz /]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10530 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3934 [OK]
# 可选项,通过收藏数来过滤(大于3000)
docker search mysql --filter=STARS=3000
docker pull 镜像下载
# 下载镜像 docker pull 镜像名[:tag]
[root@iz2ze2js0u6m077omgcbzmz /]# docker pull mysql
Using default tag: latest # 不写tag,就默认下载最新版
latest: Pulling from library/mysql
a076a628af6f: Pull complete # 分层下载,docker images的核心,联合文件系统
f6c208f3f991: Pull complete
88a9455a9165: Pull complete
406c9b8427c6: Pull complete
7c88599c0b25: Pull complete
25b5c6debdaf: Pull complete
43a5816f1617: Pull complete
1a8c919e89bf: Pull complete
9f3cf4bd1a07: Pull complete
80539cea118d: Pull complete
201b3cad54ce: Pull complete
944ba37e1c06: Pull complete
Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
选择版本下载,必须对应官网中现有的版本

[root@iz2ze2js0u6m077omgcbzmz /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
a076a628af6f: Already exists # 不会重复下载现有东西
f6c208f3f991: Already exists
88a9455a9165: Already exists
406c9b8427c6: Already exists
7c88599c0b25: Already exists
25b5c6debdaf: Already exists
43a5816f1617: Already exists
1831ac1245f4: Pull complete
37677b8c1f79: Pull complete
27e4ac3b0f6e: Pull complete
7227baa8c445: Pull complete
Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 删除镜像(通过id删除)
# 删除单个镜像
docker rmi -f 镜像id
# 删除多个镜像
docker rmi -f 镜像id 镜像id 镜像id
# 删除全部镜像
docker rmi -f $(docker images -qp) # -qp 是查询所有的id

容器命令
说明:我们有了镜像才可以创建容器,Linux
docker pull centos
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" # 容器名字 tomcat01 tomcat 02, 用来区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
-P # 随机指定端口(大写P)
启动并进入容器
# 使用-it交互模式,不然无法进入
[root@iz2ze2js0u6m077omgcbzmz /]# docker run -it centos /bin/bash
# 启动之后,发现主机名变化
# 查看的是容器内的centos文件
[root@afe08a58288f /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
# 从容器中退回主机
[root@afe08a58288f /]# exit

列出所有在运行的容器
- -a :列出当前正在运行的容器 + 历史运行过的容器
- -n=? :显示最近创建的容器
- -q :只显示容器的编号
# 查看正在运行的容器,为空
[root@iz2ze2js0u6m077omgcbzmz /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 查看曾经运行的容器
[root@iz2ze2js0u6m077omgcbzmz /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afe08a58288f centos "/bin/bash" 3 minutes ago Exited (0) About a minute ago reverent_goldwasser
b4520ec7f5c1 bf756fb1ae65 "/hello" 3 hours ago Exited (0) 3 hours ago youthful_margulis
退出容器
exit # 直接容器停止并退出
Ctrl + p + Q # 容器不停止退出
删除容器
# 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm 容器id
# 删除所有的容器
docker rm -f $(docker ps -aq)
# 删除所有的容器
docker ps -a -q|xargs docker rm
启动和停止容器的操作
# 启动容器(对于启动之后停止的容器)
docker start 容器id
# 重启容器
docker restart 容器id
# 停止容器
docker stop 容器id
# 杀掉容器
docker kill 容器id

常用的其他命令
后台启动容器
# 命令 docker run -d 镜像名
docker run -d centos
# 问题:执行docker ps 发现 centos 停止了
# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
# 添加脚本启动
[root@iz2ze2js0u6m077omgcbzmz /]# docker run -d centos /bin/sh -c "while true;do echo helloworld;sleep 1;done"
5d09f7ecc0c2a3dddcb118607728baceceed3a0a1a36449432d7e96426055562
# 查看是否在运行
[root@iz2ze2js0u6m077omgcbzmz /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5d09f7ecc0c2 centos "/bin/sh -c 'while t…" 4 seconds ago Up 3 seconds admiring_turing
查看日志
docker logs -f -t --tail [条数] [容器id]
# 编写一段shell脚本
docker run -d centos /bin/sh -c "while true;do echo helloworld;sleep 1;done"
# 查看对应的日志,并不断追踪
-f # 日志带上时间戳
-t # 显示所有日志
[root@iz2ze2js0u6m077omgcbzmz /]# docker logs -f -t --tail 10 5d09f7ecc0c2

查看容器的进程信息
# 命令:docker top 容器id(杀进程通过ppid)
[root@iz2ze2js0u6m077omgcbzmz /]# docker top 5d09f7ecc0c2
UID PID PPID C STIME TTY TIME CMD
root 785 733 0 19:40 ? 00:00:00 /bin/sh -c while true;do echo helloworld;sleep 1;done
root 2081 785 0 19:46 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
# 命令: docker inspect 容器id
[root@iz2ze2js0u6m077omgcbzmz /]# docker inspect 5d09f7ecc0c2

进入当前正在运行的容器
# 我们通常的容器都是使用后台方式进行,需要进入容器修改一些配置
# 方式一:docker exec -it 容器id /bin/bash
# 进入容器后开启一个新的终端,可以在里面操作()常用
# 测试
[root@iz2ze2js0u6m077omgcbzmz /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5d09f7ecc0c2 centos "/bin/sh -c 'while t…" About an hour ago Up About an hour admiring_turing
[root@iz2ze2js0u6m077omgcbzmz /]# docker exec -it 5d09f7ecc0c2 /bin/bash
[root@5d09f7ecc0c2 /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
# 方式二:docker attach 容器id
# 进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
测试
# 查看当前主机目录下
[root@iz2ze2js0u6m077omgcbzmz home]# ls
dst epel-release-6-8.noarch.rpm redis www
[root@iz2ze2js0u6m077omgcbzmz home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5d09f7ecc0c2 centos "/bin/sh -c 'while t…" About an hour ago Up About an hour admiring_turing
# 进入docker容器内部
[root@iz2ze2js0u6m077omgcbzmz home]# docker exec -it 5d09f7ecc0c2 /bin/bash
[root@5d09f7ecc0c2 /]# cd home
[root@5d09f7ecc0c2 home]# ls
# 在容器中新建一个文件
[root@5d09f7ecc0c2 home]# touch test.java
# 退出容器
[root@5d09f7ecc0c2 home]# exit
exit
# 将这个文件拷贝出来到主机上
[root@iz2ze2js0u6m077omgcbzmz home]# docker cp 5d09f7ecc0c2:/home/test.java /home
[root@iz2ze2js0u6m077omgcbzmz home]# ls
dst epel-release-6-8.noarch.rpm redis test.java www
# 拷贝是一个手动过程,以后可以使用 -v 卷的技术,可以实现自动同步
小结

4、安装Nginx
# 1、搜索镜像(在官网中搜索才可以看到版本信息和文档)
docker search nginx
# 2、下载镜像
docker pull nginx
# 3、启动nginx
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
docker run -d --name nginx01 -p 3344:80 nginx
# 4、测试访问端口
curl localhost:8000
# 5、停止nginx服务,停止之后就访问不了
docker stop 容器id/nginx01

端口暴露原理:相当于主机的3344端口映射到docker中的80端口

思考:我们每次要改动nginx的配置文件都需要进入容器内容,十分麻烦,是否可以在容器外部提供一个映射路径,达到在容器修改文件,容器内部就可以自动修改?
使用 -v 数据卷可以实现!
5、安装Tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止容器之后,容器还是可以查到
# docker run -it --rm 一般用来测试,用完即删
# 1、下载启动
docker pull tomcat:9.0
# 2、启动运行
docker run -d -p 9000:8080 --name tomcat01 tomcat
通过外网访问9000端口

分析出现404原因
# 进入容器
docker exec -it tomcat01 /bin/bash
# 发现问题:1、linux命令少了,2、没有webapps
# 原因:阿里云镜像默认是最小的镜像,所有不必要的都剔除掉
# 保证最小可运行环境
思考:以后要部署项目,每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,webapps我们可以在外部放置项目,就自动同步内部就好了!
6、部署 ES + Kibana
# es 暴露的端口很多
# es 十分的耗内存 1.x G
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork 为网络配置,暂时不用
# 下载启动 elasticsearch
docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 启动了之后 linux 就会卡住了! docker stats 查看cpu状态
# 查看 docker stats
# 测试以下es是否成功了
curl localhost:9200
# 赶紧关闭,增加内容的限制
docker stop 容器id

修改配置文件 -e 环境配置修改
# 修改配置文件,限制使用的内容
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
# 查看docker stats
docker stats 容器id

使用kibana连接ES
思考网络如何连接过去

7、可视化
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再用)
什么是 portainer?
Docker图形化界面管理工具!提供一个后台面板供我们操作!
# 下载portainer
docker run -d -p 8088:9000 \
--restart=always -v "/var/run/docker.sock:/var/run/docker.sock" --privileged=true portainer/portainer
访问测试:外网8088

首次加载比较久,设置用户名密码之后进入

选择使用本地仓库

连接进入

这里可以查看所有的镜像和容器

8、Docker镜像讲解
镜像是什么?
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时,库、环境变量和配置文件。
所有的应用,直接打包成为docker镜像,就可以直接跑起来!
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像 DockerFile
Docker镜像加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统):是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union 文件系统是 Docker 镜像的基础。镜像而可以通过分层来进行继承,基于镜像基础(没有父镜像),可以制作各种具体的应用镜像。
例如:
# 安装docker 第一层
# 安装centos 第二层
# 安装JDK 第三层
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与外面典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由cootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同操作系统发行版,比如Ubuntu,Centos等。

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

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见,对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
分层原理
分层的镜像
我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的下载!

思考:为什么docker镜像要采用这种分层的结构呢?
最大的好处,莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享!
查看镜像封层的方式可以通过 docker image inspect 命令
[root@iz2ze2js0u6m077omgcbzmz ~]# docker image inspect redis:latest

理解:
所有的Docker 镜像都始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,例如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在这个镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(简单的例子)

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合。如下图,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层的文件7 是文件5的一个更新版本(可以覆盖文件5)。

在这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS 文件系统之上实现了分层和 Cow。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层(无法改变)!

完整过程:

9、commit容器
提交镜像
docker commit 提交容器成为一个新的副本
# 命令和 git 原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 1、启动一个默认的tomcat
[root@iz2ze2js0u6m077omgcbzmz ~]# docker run -it -p 9000:8080 tomcat
# 2、发现这个默认的 tomcat 是没有webapps应用。这是镜像的原因,官方的镜像默认 webapps下面是没有文件的!
[root@iz2ze2js0u6m077omgcbzmz ~]# docker exec -it fc6993915d41 /bin/bash
# 3、自行拷贝进去了基本文件
root@fc6993915d41:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@fc6993915d41:/usr/local/tomcat# cd webapps
root@fc6993915d41:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
修改之后就可以看到正常的tomcat页面了

# 4、将我们操作过的容器通过 commit 提交为一个镜像!我们以后就使用修改过的镜像即可,自定义为tomcat02,版本为1.0
[root@iz2ze2js0u6m077omgcbzmz ~]# docker commit -a="xiaojiang" -m="add webapps app" fc6993915d41 tomcat02:1.0

如果想要保存当前容器的状态,就可以通过commit 来提交,获得一个镜像,就好比我们以前学习VM时候使用的快照。
10、容器数据卷
什么是容器数据卷
docker的理论回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
MySQL,容器删了,数据也没了!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!

总结:容器的持久化和同步操作!容器间也可以数据共享!
使用数据卷
方式一:直接使用命令来挂载 -v
# 就好比端口映射
docker run -it -v 主机目录:容器内目录
# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动起来之后我们可以通过 docker inspect 容器id (进行查看)
docker inspect bb59516980a9

测试文件的同步

测试:停止容器之后修改文件
- 停止容器
- 宿主机上修改文件
- 启动容器
- 容器内的数据内容依然存在

好处:我们以后修改只需要在本地修改即可,容器内会自动同步!
实战:安装MySQL
思考:MySQL 的数据持久化问题!
# 获取镜像
docker pull mysql:5.7
# 运行容器,需要做数据挂载
# 注意:安装启动mysql,需要配置密码的
# 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动我们的
# -d 后台运行
# -p 端口映射
# -v 卷挂载
# -e 环境配置
# --name 容器名字
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 -d --name mysql01 mysql:5.7
启动成功之后,我们使用本地的软件navicat来测试连接

# 连接原理:
# navicat - 连接到服务器的3310 --- 3310 和容器内的 3306 映射,这个时候我们就可以连接上了(注意开放3310端口)

测试
在本地连接Mysql并创建数据库

发现服务器目录下同样也多出了这个文件

所以就算把mysql容器删除了,但是我们挂载在本地的数据卷并不会丢失!
具名和匿名挂载
匿名挂载
# 匿名挂载,-P随机映射端口
-v 容器内路径!
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的卷的情况
docker volume ls
# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径

具名挂载
# 具名挂载
docker run -d -P --name nginx02 -v juming:/etc/nginx nginx
# 查看所有的卷的情况
docker volume ls

查看挂载的信息和目录
# 查看这个卷
docker volume inspect juming-nginx

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes目录下。
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况使用的具名挂载

查看nginx的配置文件

确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:/容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读写
# 一旦设置了容器的权限,容器对我们挂载出来的内容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部无法操作!
初识 Dockersfile
Dockerfile 就是用来构建 docker 镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个的命令,每个命令就是一层!
# 创建一个dockerfile文件
cd /home
mkdir docker-test-volume
cd docker-test-volume/
vim dockerfile01
# 编写文件内容,的hi零都是大写的,匿名挂载
FROM centos
VOLUME ["volume01", "volume02"]
CMD echo "-----end-----"
CMD /bin/bash

生成镜像
# -f 指定dockerfile文件
# -t 命名镜像
# . 表示在当前路径下生成
docker build -f dockerfile01 -t xiaojiang/centos:1.0 .

查看镜像

启动自己写的容器
# 启动容器
docker run -it 49a93c8bcf07
# 查看容器文件
ls -l

这个卷和外部一定有一个同步的目录,我们在上方使用了匿名挂载

# 查看卷挂载的路径
docker inspect 6e56e2421de7

这种方式我们未来使用的十分多,因为我们通常回构建自己的镜像!
假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名 容器内路径
数据卷容器
两个 MySQL 同步数据

测试多个容器共享数据
# 启动容器1
docker run -it --name docker01 xiaojiang/centos:1.0
# 按 ctrl + P + Q 退出界面
# 启动容器2并挂载上容器1
docker run -it --name docker02 --volumes-from docker01 xiaojiang/centos:1.0
# 进入docker01容器,编写共享文件
docker attach d3261b8b1c70
cd volumes01
touch docker01
# 在docker02容器中查看

# 创建容器3,挂载到容器2
docker run -it --name docker03 --volumes-from docker01 xiaojiang/centos:1.0

# 在docker03中编写文件,发现在其他容器中同样可以查看到
touch docker03
# 将容器1删除,查看是否回产生影响
docker rm -f docker01

发现数据依然存在

多个mysql实现数据共享
# 启动一个mysql01
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
# 启动mysql02
docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候就可以实现两个容器数据同步!
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
一旦持久化到了本地,这个时候本地的数据是不会删除的!
11、DockerFile
DockerFile 介绍
dockerfile 是用来构建 docker 镜像的文件,命令参数脚本
构建步骤:
- 编写一个 dockerfile 文件
- docker build 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub、阿里云镜像仓库)
查看一下官方用法,访问 https://hub.docker.com/,搜索centos,点击下方版本信息即可跳转到对应 GitHub 仓库查看源码


但是很多官方镜像都是基础包,很多功能没有,通常需要我们自己搭建镜像!
DockerFile 构建过程
基础知识
每个保留关键字(指令)都是必须大写字母
执行顺序为从上到下
#表示注释每一个指令都会创建提交一个新的镜像层,并提交

dockerfile 是面向开发的,我们以后要发布项目,做镜像,就需要编写 dockerfile 文件。
步骤
DockerFile:构建文件,定义一切的步骤,源代码
Docker镜像:通过 DockerFile 构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来提供服务
DockerFile 指令
可以通过以下指令,构建自己的镜像
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名 + 邮箱
RUN # 惊醒构建的时候需要运行的命令
ADD # 添加其他内容要这个镜像中
WORKDIKR # 镜像的工作目录
VOLUME # 挂载的目录,-v
EXPOSE # 保留端口配置,-p
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个生效
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令
COPY # 类似ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量,-e

实战测试
基础镜像
Docker Hub 中大部分镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建

创建一个自己的centos
1、编写 DockerFile 文件
vim mydockerfile-centos
FROM centos
MAINTAINER luxiaojiang<1256240778@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
2、通过这个文件构建镜像
# 命令 docker build -f dockerfile -t 镜像名:[tag] [文件路径]
docker build -f mydockerfile-centos -t mycentos:1.0 .

报错了:The command ‘/bin/sh -c yum -y install vim’ returned a non-zero code: 1
原因:docker中的centos版本对应不上,需要设置版本,宿主机上的centos是7
FROM centos:7
修改好版本之后即可

3、运行镜像
docker run -it mycentos:1.0

此时可以发现直接进入到工作目录,这是编写 dockerfile 文件的时候设置的
并且发现 ifconfig 和 vim 指令也可以使用了

查看镜像的变更历史
# docker history [镜像id]
docker history af69beb2f34e

CMD 和 ENTRYPOINT 区别
CMD # 指定容器启动的时候要运行的命令,只有最后一个生效,最后一个替换此前的命令
ENTRYPOINT # 指定容器启动的时候要运行的命令,可以不断追加命令指令
CMD测试
# 创建 dockerfile 文件
vim dockerfile-cmd-test
FROM centos
CMD ["ls", "-a"]
# 生成镜像
docekr build -f dockerfile-cmd-test -t cmdtest:1.0 .
# 运行镜像
docker run 96ea83f47d80
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 测试追加命令
docker run 96ea83f47d80 -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
ENTRYPOINT测试
# 创建 dockerfile 文件
vim dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls", "-a"]
# 生成镜像
docker build -f dockerfile-entrypoint-test -t entrypoint-test:1.0 .
# 执行镜像
docker run de9251f23f04
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 追加命令测试
docker run de9251f23f04 -l
total 56
drwxr-xr-x 1 root root 4096 May 29 14:00 .
drwxr-xr-x 1 root root 4096 May 29 14:00 ..
-rwxr-xr-x 1 root root 0 May 29 14:00 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 May 29 14:00 dev
drwxr-xr-x 1 root root 4096 May 29 14:00 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 114 root root 0 May 29 14:00 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 May 29 14:00 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
制作 Tomcat 镜像
1、准备镜像文件 tomcat 压缩包,jdk 的压缩包
下载jdk:https://www.oracle.com/java/technologies/downloads/

下载tomcat:https://tomcat.apache.org/download-90.cgi

上传至服务器

2、编写 dockerfile 文件,官方命名 Dockerfile,构建镜像的时候 build 会自动寻找这个文件,就不需要 -f 指定了
# 创建文件
touch redme.txt
# 编写 dockerfile
# COPY 用于直接复制文件
# ADD 会添加并解压
vim Dockerfile
FROM centos:7
MAINTAINER luxiaojiang<1256240778@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u333-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.63.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_333
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.63
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.63
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD $CATALINA_HOME/bin/startup.sh && tail -F $CATALINE_HOME/bin/logs/catalina.out
3、构建镜像
# 因为文件直接命令为 Dockerfile,所以不需要加 -f 命令
docker build -t luxiaojiang123/diytomcat:1.0 .

4、运行镜像
# -d 后台运行
# -p 指定端口映射
# --name 设置容器名称
# -v 挂在目录
docker run -d -p 9000:8080 --name lxjtomcat -v /usr/local/docker/tomcat/test:/usr/local/apache-tomcat-9.0.63/webapps/test -v /usr/local/docker/tomcat/logs:/usr/local/apache-tomcat-9.0.63/logs luxiaojiang123/diytomcat
5、进入容器
docker exec -it acea24c093fd /bin/bash
6、退出容器,测试访问
exit
# 在宿主机访问测试
curl localhost:9000

7、测试目录挂载
# 进入容器
docker exec -it 775e83020e9b /bin/bash
cd /usr/local/apache-tomcat-9.0.63/webapps/test
8、在宿主机创建 jsp 文件
cd /usr/local/docker/tomcat/test
vim index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello,luxiaojiang</title>
</head>
<body>
hello, world! <br/>
<%
System.out.println("----my test web logs-----");
%>
</body>
</html>
9、可以查看到容器内的挂载目录也新增了一个文件

10、访问测试

项目部署成功之后就可以直接访问了
以后的开发步骤:需要掌握 Dockerfile 的编写!我们之后的一切都是使用 docker 镜像来发布运行!
发布到 DockerHub
DockerHub

2、注册完账号之后直接在服务器上进行登录
(base) ? tomcat docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
3、登录完成之后直接提交就行

4、提交镜像
# docker push [用户名]/[镜像名]
docker push luxiaojiang123/diytomcat

5、登录 DockerHub 查看是否上传成功


发布到阿里云
1、登录阿里云
2、找到容器镜像服务
3、创建命名空间

4、创建镜像仓库

选择本地仓库

就可以看到相应的操作指南了

5、测试
# 进行登录
docker login --username=晓江233 registry.cn-shenzhen.aliyuncs.com

# 重新构建镜像,命名为 [用户名]/[镜像名]
docker build -t registry.cn-shenzhen.aliyuncs.com/luxiaojiang/diytomcat:1.0 .
# 也可以直接重命名本地镜像名称,并生成相应副本(不是修改原镜像)
docker tag [镜像id] [仓库名]:[版本]

# 推送镜像到阿里云
docker push registry.cn-shenzhen.aliyuncs.com/luxiaojiang/diytomcat:1.0

上传成功之后就可以在阿里云中查看到对应的镜像了

小结

12、Docker网络
Docker0
测试
1、获取 docker 的 ip 地址
ip addr

问题:docker 是如何处理容器网络访问的?

2、启动 tomcat 容器
docker run -d -P --name tomcat01 tomcat
3、查看容器的 ip 地址
docker exec -it tomcat01 ip addr
报错:OCI runtime exec failed: exec failed: unable to start container process: exec: “ip”: executable file not found in $PATH: unknown

解决:
# 执行以下命令
apt update && apt install -y iproute2
4、发现容器启动的时候会得到一个 eth0 ip地址,这是 docker 分配的,并且可以直接 ping 通 docker 容器内部

原理
1、我们每启动一个 docker 容器,docker 就会给 docker 容器分配一个 ip,我们只要安装了 docker,就会有一个网卡 docker0
2、使用桥接模式,evth-pair 技术
3、再启动一个容器测试,发现又多一个一对网卡

# 我们发现这个容器带来的网卡,都是一对对的
# evth-pair 就是一堆的虚拟设备接口,都是成对出现的,一端连接着协议,一端彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# OpenStac,Docker 容器之间的连接,OVS 的连接,都是使用 evth-pair 技术
4、测试两个容器能否相互连接
# 查看 tomcat01 的 ip 地址
docker exec -it tomcat01 ip addr
# 使用 tomcat02 ping tongcat01
docker exec -it tomcat02 ping 172.17.0.2
报错:OCI runtime exec failed: exec failed: unable to start container process: exec: “ping”: executable file not found in $PATH: unknown

解决:算了,并没有解决,反正能 ping 通的
docker exec -it tomcat02 /bin/bash
apt-get update && apt-get install iputils-ping
5、原理图如下

结论:tomcat01 和 tomcat02 是公用一个路由器的,docker0
所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用ip
小结
Docker 使用的是 Linux 的桥接,宿主机中是一个 Docker 容器的网桥,docker0

Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高
只要容器删除,对应的一对网桥就没了
查看网络
# 查看网络列表
docker network ls

# 查看桥接网络
docker inspect 07cb58b73881
这是 docker0 的网络配置

往下可以查看到 docker 的容器网络

–link
思考
编写了一个微服务,database url = ip;项目一重启,数据库 ip 就换掉了,我们希望可以解决这个问题,可以通过名字来进行访问容器
# 如果直接使用容器名ping不通
docker exec -it tomcat02 ping tomcat01
使用 –link 命令
# 重新启动一个容器
docker run -d -P --name tomcat03 --link tomcat02 tomcat
这样启动之后,tomcat03 就可以 ping 通tomcat02
注意:当时 tomcat02 不能 ping 通 tomcat03
原理
# 查看 tomcat03 的网络本地配置
docker exec -it cat /etc/hosts

# 查看 tomcat02 的网络配置
docker exec -it tomcat02 cat /etc/hosts
这里并没有 tomcat03 的网络映射,所以 tomcat02 连接不通 tomcat03

本质:–link 就是在 hosts 配置中增加一个映射关系
但是现在已经不建议使用 –link 了
自定义网络
查看所有的 docker 网络

网络模式
bridge:桥接 docker(默认)
none:不配置网络
host:和宿主机共享网络
container:容器网络连通(用的少,局限很大)
测试
# 我们直接启动的命令自动使用 --net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0 特点:默认,不能通过容器名访问,--link 可以打通连接
自定义网络
# 创建网络
# --driver 定义网络模式
# --subnet 设置掩码,/16 表示前面八位二进制固定,剩下 255 * 255 - 2 个地址
# --gateway 设置网关
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet


启动容器并配置网络
# --net 用于设置网络
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
# 查看自定义网络
docker network inspect mynet
此时可以看到自定义网络中新增了两个容器的网络信息

测试连接
# 以下请求都能 ping 通
docker exec -it tomcat-net-01 ping 192.168.0.3
docker exec -it tomcat-net-01 ping tomcat-net-02
我们自定义的网络 docker 都已经帮我们维护好了对应的关系
好处
可以用于配置不通的网络集群,例如 redis、mysql 各自的网络集群
网络连通


# 测试打通
docker network connect mynet tomcat01
成功将 tomcat01 添加在 mynet 网络中,此时一个容器有两个 ip,配置之后,tomcat01 就能和 tomcat-net-01 连通了

实战:部署 Redis 集群

1、创建网络
docker network create redis --subnet 172.38.0.0/16
2、编写脚本创建六个 redis 配置
for port in $(seq 1 6); \
do \
mkdir -p /usr/local/docker/redis/node-${ port} /conf
touch /usr/local/docker/redis/node-${ port} /conf/redis.conf
cat << EOF >/usr/local/docker/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
直接粘贴到xshell中执行即可

3、启动六个 redis 容器
for port in $(seq 1 6); \
do \
docker run -p 637${ port} :6379 -p 1637${ port} :16379 --name redis-${ port} -v /usr/local/docker/redis/node-${ port} /data:/data -v /usr/local/docker/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
done

4、创建集群
# 进入一个 redis 容器中
docker exec -it redis-1 /bin/sh
# 创建集群
# --replicas 1 中的1其实代表的是一个比例,就是主节点数/从节点数的比例,先是3个主节点,然后是3个从节点
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

5、连接 redis 集群
# -c 代表连接集群
redis-cli -c
# 查看集群信息
cluster info
# 查看节点
cluster nodes

6、测试存值,并且关闭一台服务
set name xiaojiang

可以发现,进行存值的时候,是主机轮流进行处理
7、停止 redis-2 容器进行测试
# 新建命令窗口,停止 redis-2
docker stop redis-2

8、再次取值
get name

此时发现是从 redis-6 从机中取到值,查看集群节点,可以看到 redis-2 发生故障,redis-6 成为主机,重启 redis-2 容器之后,发现 redis-2 成为从机

SpringBoot微服务打包成Docker镜像
1、构建 springboot 项目,编写一个 hello,world 的 controller 就行了
2、打包应用
3、编写 dockerfile
FORM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
4、将 jar 和 dockerfile 文件上传到服务器

5、构建镜像
docker build -t springboot-test .
6、运行镜像
docker run -d -p 9000:8080 springboot-test

以后我们使用了 Docker 之后,给别人交付的就是一个镜像了。
但是如果有很多个镜像需要启动,则会很麻烦,所以后续就需要使用 Docker Compose 容器编排等内容。
13、Docker 小结
拉取镜像
1、登录 DockerHub 官网进行搜索镜像:https://hub.docker.com/

2、复制项目里面的拉取代码运行就可以了

运行镜像
# -it 交互方式运行 -d 后台运行
# --name 定义容器名
# -p 端口映射 -P 随机端口
# -v 目录挂载
docker run -it --name [容器名] -p 9000:8080 -v /usr/local/docker:/docker [镜像名]
提交容器
# 提交容器成为一个新的副本
# 命令和 git 原理类似
docker commit -m="提交的描述信息" -a="作者" [容器id] [目标镜像名]:[TAG]
提交镜像
1、提交到 DockerHub
# 登录 DockerHub
docker login -u luxiaojiang123
# 生成镜像副本,将目标镜像命名为 [用户名]/[镜像名]
docker tag [原镜像]:[TAG] [目标镜像]:[TAG]
# docker push [用户名]/[镜像名]
docker push luxiaojiang123/diytomcat
2、提交到 阿里云容器镜像服务
# 登录账号
docker login --username=晓江233 registry.cn-shenzhen.aliyuncs.com
# 生成镜像副本
docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/luxiaojiang/diytomcat:[镜像版本号]
# 提交镜像
docker push registry.cn-shenzhen.aliyuncs.com/luxiaojiang/diytomcat:[镜像版本号]
- 本文链接:https://lxjblog.gitee.io/2022/06/05/Docker%E5%AE%B9%E5%99%A8/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。