侧边栏壁纸
博主头像
威风博主等级

九万里风鹏正举,风休住,蓬舟吹取三山去。

  • 累计撰写 38 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Docker

威风
2020-09-16 / 0 评论 / 0 点赞 / 172 阅读 / 23,184 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-09,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

环境 : 阿里云服务器 centos7

Dcoker概述

Docker为什么会出现?

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

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

开发即运维!

环境配置十分麻烦,每个机器都要部署环境(集群Redis,ES,Hadoop…) 费时费力

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

之前在服务器配置一个应用的环境Redis MySQL jdk ES Hadoop , 配置超麻烦,不能跨平台

Windows开发,发布到Linux上.

传统:开发打包成jar ,运维来做环境部署.

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

比如一个安卓应用 java – apk – 发布 (应用商店) --张三使用apk – 安装即可用

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

Docker的思想来自于集装箱

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

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

Docker给以上的问题,提出了解决方案.

img

虚拟机技术缺点:

1, 资源占用十分多

2, 冗余步骤多

3, 启动很慢

容器化技术

容器化技术并不是模拟一个完整的操作系统

img

比较Docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一条硬件,运行一个 完整的操作系统,然后在这个系统上安装和运行软件-
  • 容器内的应用直接运行在宿主机的内容, 容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
  • 每个容器间是相互隔离的,每个容器内部都有一个属于自己的文件系统,互不影响
应用更快速的交付和部署

传统:一堆帮助文档,安装程序

Docker:打包镜像发布测试,一键运行

更便捷的升级和扩缩容

使用了Docker之后,我们部署应用就和搭积木一样

项目打包为一个镜像,水平扩展服务器A,服务器B

更简单的系统运维系统

在容器化之后,我们的开发,测试环境都是高度一致的.

更高效的计算资源利用

1核2g的服务器 可以同时运行几十个tomcat?!!!

Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例

服务器的性能可以被压榨到极致!

Docker安装 请参考视频

狂神说

1 Docker的常用命令

1.1帮助命令


# docker 看docker版本

docker version

#docker 信息

docker info

#docker 万能命令

docker 命令 --help

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

1.2镜像命令


1.2.1 查看镜像

# 查看本机所有本地镜像

docker images

#解释

REPOSITORY 镜像的仓库源

TAG 镜像的标签

IMAGE ID 镜像的ID

CREATED 镜像的创建时间

SIZE 镜像的大小

# 命令的可选项

-a, --all 列出所有镜像

-q, --quiet 只显示镜像的ID

img

1.2.2搜索镜像

# 搜索镜像

docker search 镜像

#可选项 通过收藏来过滤s

--filter=STARS=3000 # 搜索的镜像就STARS大于3000以上的

img

img

1.2.3下载镜像

#下载镜像 docker pull 镜像名[:tag]

[root@weifeng demo]# docker pull mysql

Using default tag: latest #如果没指定版本会下载最新的

latest: Pulling from library/mysql#

afb6ec6fdc1c: Pull complete #分层下载 docker image的核心联合文件系统

0bdc5971ba40: Pull complete

97ae94a2c729: Pull complete

f777521d340e: Pull complete

1393ff7fc871: Pull complete

a499b89994d9: Pull complete

7ebe8eefbafe: Pull complete

597069368ef1: Pull complete

ce39a5501878: Pull complete

7d545bca14bf: Pull complete

0f5f78cccacb: Pull complete

623a5dae2b42: Pull complete

Digest: sha256:beba993cc5720da07129078d13441745c02560a2a0181071143e599ad9c497fa

Status: Downloaded newer image for mysql:latest

docker.io/library/mysql:latest # 真实地址

# 下面两个命令是一个意思

docker pull mysql

docker pull docker.io/library/mysql:latest

#指定版本下载

[root@weifeng demo]# docker pull mysql:5.7

img

img

1.2.4删除镜像

#通过id删除 docker rmi -f 镜像id

[root@weifeng demo]# docker rmi -f b84d68d0a7db

img

#批量删除

docker rmi -f $(docker images -aq)

img

1.3 容器命令


说明: 有了镜像才可以创建容器,使用linux镜像来学习

1.3.1 运行容器

#下载centos镜像

docker pull centos

img

# 运行镜像

docker run [可选参数] images

# 参数说明

--name="Name" 容器名字 tomcat1 tomcat2 用了区分容器

-d 后台方式运行

-it 使用交互方式运行,进入容器查看内容

#注意 p(小写) P(大写)

-p 指定容器的端口 -p 8080:8080

​ -p ip:主机端口:容器端口

​ -p 主机端口: 容器端口(常用)

​ -p 容器端口

-P 指定随机端口

#测试 启动并进入容器

[root@weifeng demo]# docker run -it centos /bin/bash

[root@211e4bb80345 /]# ls # 查看内部容器的centos

bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

img

1.3.2退出容器

# 退出 后容器停止

[root@211e4bb80345 /]# exit

# 容器不停止退出

Ctrl+P+Q

img

1.3.3列出运行的容器

#docker ps 命令

# 当前正在运行的容器

-a #列出当前正在运行的容器+带出历史运行过的容器

-n=?#列出最近创建的容器

-p #只显示容器的编号

#列出运行的容器

[root@weifeng demo]# docker ps

#列出

[root@weifeng demo]# docker ps -a

#列出最近创建的容器 n后面数字可选

[root@weifeng demo]# docker ps -a -n=1

#只显示容器的编号

[root@weifeng demo]# docker ps -aq

img

img

1.3.4 删除容器

#删除指定容器 运行中的不能删 如果强制删除 需要加 -f 参数(docker rm -f 容器id)

docker rm 容器ID

#删除所有容器

docker rm -f $(docker ps -aq)

img

img

1.3.5 启动和停止容器的操作

# 启动容器

docker start 容器ID

img

#停止正在运行容器

docker stop 容器ID

img

docker restart 容器ID #重启容器

docker kill 容器ID #强制停止当前容器

1.4常用的其他命令

1.4.1 后台启动容器

# 命令 docker run -d 镜像名

[root@weifeng demo]# docker run -d centos

c29b4906c418eb979e3dd111015508eca9e520cb08e6df51d5b41c5af2ab73c0

[root@weifeng demo]# docker ps

# 问题docker ps 发现 centos 停止了

# 常见的坑,docker 容器使用后台运行 必须要有一个前台进程,否则docker就会自动停止

img

1.4.2 查看日志

docker logs

-f :跟踪日志输出

--since :显示某个开始时间的所有日志

-t :显示时间戳

--tail :仅列出最新N条容器日志

#例子 运行容器 循环打印hello

[root@weifeng demo]# docker run -d centos /bin/bash -c "while true;do echo hello;sleep 1;done"

#显示日志 docker logs -tf --tail 10 容器ID

[root@weifeng demo]# docker logs -tf --tail 10 40123a87d3a1

img

img

1.4.3查看容器中进程ID

# docker top 容器ID

docker top 40123a87d3a1

img

1.4.4查看镜像|容器元数据

#查看容器元数据

docker inspect 容器ID

[root@weifeng ~]# docker ps -aq

aa6357c78b8f

40123a87d3a1

763aa3e14833

b9d4012f2b72

37c3a8b11187

c29b4906c418

bbdd3d3fe2ff

[root@weifeng ~]# docker inspect aa6357c78b8f

[

{

​ "Id": "aa6357c78b8f51a724642f82c6fb329c4548dc8d4cae8644698f62bbd7573c09",

​ "Created": "2020-05-17T00:14:35.849665997Z",

​ "Path": "/bin/bash",

​ "Args": [],

​ "State": {

​ "Status": "exited",

​ "Running": false,

​ "Paused": false,

​ "Restarting": false,

​ "OOMKilled": false,

​ "Dead": false,

​ "Pid": 0,

​ "ExitCode": 0,

​ "Error": "",

​ "StartedAt": "2020-05-17T00:14:36.695023294Z",

​ "FinishedAt": "2020-05-17T00:18:06.576675345Z"

​ },

.....略

]

img

img

1.4.5进入当前运行的容器

#我们通常都是使用后台的方式运行容器,有时需要进入容器,修改一些配置

# 命令 方式一

docker exec -it 容器id bashShell

# 方式二

[root@weifeng ~]# docker attach 容器ID

#两种区别

docker exec #进入容器后开启一个新的终端,可以在里面操作(常用)

docker attach #进入容器正在执行的终端,不会启动新的进程

方式一

img

方式二

img

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

docker cp 容器id:容器内文件路径 目的主机路径

#查看运行的容器

[root@weifeng ~]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c7c90ac66437 centos "/bin/bash" 18 minutes ago Up 39 seconds angry_cohen

#进入容器

[root@weifeng ~]# docker attach c7c90ac66437

[root@c7c90ac66437 home]# ls

my.java

[root@c7c90ac66437 home]# read escape sequence

#拷贝到/home文件下

[root@weifeng ~]# docker cp c7c90ac66437:/home/my.java /home

[root@weifeng ~]# ls

auto_disk.sh bt-uninstall.sh demo install.sh softwore

[root@weifeng ~]# cd /home/

[root@weifeng home]# ls

cao my.java redis www

#拷贝式一个手动过程,之后可以通过 -v 卷的技术,可以实现文件自动同步

img

小结

img

img

img

docker 的命令是非常多的 ,上面只是最常用的命令

2 Docker 的练习

Docker安装nginx

2.1 安装nginx

  1. 搜索镜像 search 建议去dockerhub搜索 可以看到详细信息
    dockerHub地址:docker仓库地址
    img
  2. docker pull nginx
    img
  3. 步骤
[root@weifeng ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              9beeba249f3e        29 hours ago        127MB
centos              latest              470671670cac        4 months ago        237MB
#后台启动nginx 起名 nginx01 暴露端口号为20884(注意此端口需要你的服务器开放了此端口)
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
[root@weifeng ~]# docker run -d --name nginx01 -p:20884:80 nginx
6abddc1ce2eed5ecf4a1ae52026191c2d1a27c24c743b63e8c66379c450ba831
[root@weifeng ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
6abddc1ce2ee        nginx               "nginx -g 'daemon of…"   7 seconds ago       Up 6 seconds        0.0.0.0:20884->80/tcp   nginx01
c7c90ac66437        centos              "/bin/bash"              56 minutes ago      Up 38 minutes                               angry_cohen
#测试
[root@weifeng ~]# curl localhost:20884
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    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>
#进入容器
[root@weifeng ~]# docker exec -it nginx01 /bin/bash
root@6abddc1ce2ee:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@6abddc1ce2ee:/# cd /etc/nginx/ 
root@6abddc1ce2ee:/etc/nginx# ll
bash: ll: command not found
root@6abddc1ce2ee:/etc/nginx# ls
conf.d  koi-utf  mime.types  nginx.conf   uwsgi_params
fastcgi_params	koi-win  modules     scgi_params  win-utf
root@6abddc1ce2ee:/etc/nginx#
  1. 端口暴露的概念
    img

2.2安装tomcat

#官方的命令 容器用完就删 做测试可以用
docker run -it --rm tomcat:9.0
#下载在启动
[root@weifeng ~]# docker pull tomcat:9.0
9.0: Pulling from library/tomcat
Digest: sha256:ce753be7b61d86f877fe5065eb20c23491f783f283f25f6914ba769fee57886b
Status: Image is up to date for tomcat:9.0
docker.io/library/tomcat:9.0
#启动
[root@weifeng ~]# docker run -d -p 20885:8080 --name tomcat01 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
Digest: sha256:ce753be7b61d86f877fe5065eb20c23491f783f283f25f6914ba769fee57886b
Status: Downloaded newer image for tomcat:latest
17aefd39887d6a5adbd1cd272957da8bc0344c2a12912ba92179c4906c3c19b0
#进入容器
[root@weifeng ~]# docker exec -it tomcat01 /bin/bash
root@17aefd39887d:/usr/local/tomcat# ls
BUILDING.txt  LICENSE  README.md  RUNNING.txt  conf  logs     temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin       lib   native-jni-lib  webapps  work

#问题 1.linux命令少了 2.没有webapps

#原因 阿里云镜像默认是最小的镜像,所以不必要的都剔除了 保证最小可运行的环境

root@17aefd39887d:/usr/local/tomcat# cd webapps

root@17aefd39887d:/usr/local/tomcat/webapps# ls

root@17aefd39887d:/usr/local/tomcat/webapps#

# 注意 因为webapps里面没有文件 所以外部访问404

#解决

root@17aefd39887d:/usr/local/tomcat# ls

BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist

CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work

#进入到webapps.dist目录

root@17aefd39887d:/usr/local/tomcat# cd webapps.dist/

root@17aefd39887d:/usr/local/tomcat/webapps.dist# ls

ROOT docs examples host-manager manager

root@17aefd39887d:/usr/local/tomcat/webapps.dist# cd ../

# 将webapps.dist目录下的文件拷贝到webapps目录下

root@17aefd39887d:/usr/local/tomcat# cp -r webapps.dist/* webapps

root@17aefd39887d:/usr/local/tomcat# cd webapps

root@17aefd39887d:/usr/local/tomcat/webapps# ls

ROOT docs examples host-manager manager

root@17aefd39887d:/usr/local/tomcat/webapps#

img

解决

img

2.3 安装Elasticsearch和Kibana

 #es暴露的端口很多
#es十分的耗内存
#es的数据一般要放置到安全目录!挂载
# --net somentwork ?网络配置
#启动 
docker run -d --name elasticsearch  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
#启动了 liunx就卡住了 不建议这样用 服务器配置高的随意 我的直接卡住了
docker stats 查看

img

#es是十分耗内存的 启动可以增加内存的限制,修改配置文件 -e 环境配置修改

docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

#再次查看(注意 这个命令的容器和之前的容器名相同了 把之前的删掉就行了)

#启动后就运行的快了

img

#查看

[root@weifeng ~]# curl localhost:9200

img

2.4 Docker可视化

  • portainer (先用这个)
  • Rancher(CI/CD再用)

protainer

Docker 图形化界面管理工具!提供一个后台面板供我们操作!

docker run -d -p 8088:9000 \

--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

img

访问8088 第一次加载会很慢 等待即可

img

自己设置密码即可 密码长度大于八位

img

3 Docker镜像讲解

3.1镜像是什么


推荐看视频理解

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

所有的应用,直接打包docker镜像,就可以直接跑起来!

如何得到镜像:

  • 从远程仓库下载
  • 朋友拷贝给你
  • 自己制作一个镜像 Docker FIle

3.2 Docker镜像加载原理

UnionFS(联合文件系统)

UnionFS联合文件系统是一种分层的,轻量级并且高性能的文件系统,它最大的特点就是可以支持对文件的修改作为一次提交来一层层放叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下(unite several directiories into a single virtual filesystem。UnionFS联合文件系统是Docker镜像的基础,镜像可以通过分层来继承,基于基础镜像可以制作成各种应用镜像。

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

img

虚拟机式分钟级别,容器是秒级!

img

img

img

img

img

3.3 commit镜像

docker commit 提交容器成为一个新的副本

docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

测试

#启动默认的tomcat

docker run -it -p 8080:8080 tomcat /bin/bash

#发现这个默认的tomcat是没有webapps应用 ,镜像的原因 官方的镜像默认webapps 是没有文件的

#手动拷贝进去

#将修改后的容器 通过commit 提交为一个镜像! 以后就可以使用修改后的镜像了

[root@weifeng ~]# docker commit -a="卫风" -m="add webapps" 482f029ecab1 tomcat02:1.0

自己创建镜像

img

如果你想要保存当前容器的状态,就可以通过commit来提交,来获得一个镜像

类似于虚拟机的快照

4 容器数据卷

4.1什么是数据卷

docker的理念回顾

将应用和环境打包成一个镜像!数据?如果都在容器中,那么我们容器删除,数据就会丢失! 需求: 数据可以持久化

MySQL,容器删了,删库跑路! 需求: Mysql 数据可以存储在本地!

容器之间可以有一个数据共享的技术! Docker容器中产生的数据,同步到本地!

这就是卷技术! 目录的挂载,将我们的容器内的目录挂载到Liunx上面

img

总结:容器化的持久化和同步操作,容器间也可以数据共享的!

4.2使用数据卷


方式一:直接使用命令来挂载 -v

docker run -it -v 主机目录:容器内目录

#测试

[root@weifeng test]# docker run -it -v /home/test/:/home centos /bin/bash

img

查看容器元数据

docker inspect 容器id

[root@weifeng test]# docker inspect 5c1c442d3e5a

#找到mounts可以看到挂载

img

#测试

在容器内部的操作会自动同步到容器外挂载的目录 类似vue双向绑定

img

  1. 停止容器
  2. 在宿主机上修改文件
  3. 启动容器
  4. 容器内的数据依旧是同步的

好处: 我们以后修改只需要在本地修改即可,容器会自动同步!

4.3 安装MySql

MySQL的数据库持久化的问题

#下载mysql

[root@weifeng test]# docker pull mysql:5.7

img

#运行容器 ,需要做数据挂载 配置mysql的账户密码

#官方 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

#实际运行的命令 根据情况自己修改即可

# -d 后台运行

# -p 端口映射

# -v 卷映射 可以配置多个

# -e 环境配置

# -name 容器名字

[root@weifeng ~]# docker run -d -p 28885: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

img

通过外部访问成功

img

用sqlyog创建数据库 会同步到宿主机挂载的目录下

img

此时就算把容器删除,挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

4.4 具名和匿名挂载

#匿名挂载

-v容器 容器内路径!

docker run -d -p --name nginx01 -v /etc/nainx nginx

#查看所有的volume的情况

[root@weifeng test]# docker volume ls

DRIVER VOLUME NAME

local 45a74152a07762e29e08569ada14eddeda23afc717be8d6a18d7326960926ad4

#这里发现,这就是匿名挂载,我们在 -v 里只写了容器内的路径,没有写容器外的路径

#具名挂载

[root@weifeng test]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx

3aab8c7c6c12f7e8a86956e347fa38a38b6c13c3b632298b9324a4a3df6b3bba

[root@weifeng test]# docker volume ls

DRIVER VOLUME NAME

local juming-nginx

# 通过 -v 卷名:容器内路径

# 查看这个卷

img

所有的docker容器内的卷,没有指定目录的情况下 都是在 /var/lib/docker/volume/***(卷名)/data

我们通过具名挂载可以方便的找到我们的一个卷 推荐使用具名挂载

#如何确定是具名挂载还是匿名挂载,还是指定路劲挂载

-v 容器内路劲 #匿名挂载

-v 卷名:容器内路劲 #具名挂载

-v /宿主机路劲:容器内路径 #指定路劲挂载

#扩展 通过 -v 容器内路径:ro或者rw 改变读写权限

#ro readonly 只读

#rw readwrite 可读可写

# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了!

[root@weifeng _data]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx

###或者

[root@weifeng _data]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx

# ro 只有看到ro就说明这个路劲只能通过宿主机来操作,容器内部是无法操作!

方式二

一 创建一个dockerfie文件 ,名字可以随机 建议 Dockerfile

#通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "------end-------"

CMD /bin/bash

[root@weifeng docker-test-volume]# docker build -f dockerfile1 -t my/centos:1.0 .

#这里的每个命令就是镜像的一层

img

img

#启动自己生成的镜像

img

img

查看一些卷挂载的路劲

img

测试一下刚才的文件是否同步出去了!

这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!

假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径

4.5数据卷容器


多个mysql同步数据!

img

#启三个容器

[root@weifeng ~]# docker run -it --name docker1 f76d77329573

[root@weifeng ~]# docker run -it --name docker02 --volumes-from docker1 f76d77329573

[root@weifeng ~]# docker run -it --name docker03 --volumes-from docker1 f76d77329573

img

进去docker01目录下创建文件

img

不停止退出进去docker02 和docker03 分别查看

img

img

此时发现另两个容器也有docker01文件

docker01文件同步到docker02和docker03容器

只要有一个容器存在数据依旧可以访问

img

多个mysql实现数据共享

[root@weifeng ~]# docker run -d -p 28885:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

[root@weifeng ~]# docker run -d -p 28885:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 volumes-form mysql01 mysql:5.7

#这个时候可以实现两个容器数据同步!

结论:

容器之前配置信息的传递,数据容器的生命周期 一直持续倒没有容器使用为止

但是一旦你持久化到了本地,这个时候,本地的数据库是不会删除的!

5 初始Dockerfile

5.1自定义镜像

Dockerfile就是用来构建docker 镜像的构建文件! 就是命令脚本

构建步骤:

  1. 编写一个dockerfile文件
  2. docker build 构建成为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(DockerHub,阿里云镜像仓库!)

查看官方怎么做的?

img

点击版本信息 以centos7 为例

img

很多官方的镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,那我们也可以!

5.2DockerFile构建过程

基础知识

  1. 每个保留关键字(指令)都是必须是大写字母
  2. 执行从上到下顺序执行
  3. #表示注释
  4. 每一个指令都会创建一个新的镜像层,并提交!

img

dockerfile是面向开发的,我们以后发布项目,做镜像,就需要编写dockerFile文件,这个文件十分简单

Docker镜像逐渐成为企业交付的标准,必须要掌握!

  • DockerFile : 构建文件,定义了一个一切的步骤,源代码
  • DocekrImages : 通过DockerFile构建生成的镜像,最终发布运行的产品
  • Docker容器 : 容器就是镜像运行起来提供服务器

5.3 学习dockerFile的指令

img

FROM # 基础镜像,一起从这里开始构建

MAINTAINER # 镜像是谁写的,姓名+邮箱

RUN # 镜像构建的时候需要运行的命令

ADD # 编译镜像时复制文件到镜像中,比如添加个tomcat镜像

WORKDIR # 镜像的工作目录

VOLUME # 挂载的目录

EXPOSE # 暴露端口配置

CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,且可被替代

ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令

ONBUILD # 当构建一个被继承的 DockerFile 这个时候就会运行ONBUILD 的指令,触发指令

COPY # 类似ADD, 将我们的文件拷贝到镜像中

ENY # 构建的时候设置环境变量

5.4 实战测试


Docker Hub中 99%

镜像都是从这个基础镜像过来的 FROM scratch 然后配置需要的软件和配置来进行的构建

img

创建一个自己的CentOS镜像

编写dockerFile文件

vim mydockerfile

FROM centos

MAINTAINER weifeng1783246945@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

通过这个镜像构建镜像

#命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]

[root@weifeng dockerfile]# docker build -f mydockerfile -t mycentos:0.1 .

#最后成功标识

Successfully built d97c9630e08e

Successfully tagged mycentos:0.1

# 进行测试

对比 : 之前的工作目录默认是根目录,没有ifconfig 和 vim

img

自己创建的镜像

img

我们可以列出本地镜像的变更历史

# 命令 docker history 镜像id

[root@weifeng dockerfile]# docker history d97c9630e08e

img

我们平时拿到一个镜像可以研究它是怎么做的

CMD 和 ENTRYPOINT 的区别

CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,且可被替代

ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令

测试CMD

#建dockerfile文件

vim cmd-test

#内容

FROM centos

CMD ["ls","-a"]

#执行构建

[root@weifeng dockerfile]# docker build -f cmdtest -t cmdtest .

#成功之后直接执行构建后的镜像

[root@weifeng dockerfile]# docker run c63eb140ebc4

#发现ls-a 生效了

.

..

.dockerenv

bin

dev

etc

home

lib

lib64

lost+found

media

mnt

# 测试追加个命令

[root@weifeng dockerfile]# docker run c63eb140ebc4 -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.

[root@weifeng dockerfile]#

# 因为cmd 的情况下 -l 替换了 CMD["ls","a"]命令, -l 不是命令所以报错!

测试 ENTRYPOINT

#创建dockerfile文件

vim vim dockerfile-cmd-entrypoint

#编写内容

FROM centos

ENTRYPOINT ["ls","-a"]

#保存后退出 进行构建 注意 后面的 . 不要忘了

[root@weifeng dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .

# 构建完运行此镜像

[root@weifeng dockerfile]# docker run bd8100b2acff

# 输出结果

.

..

.dockerenv

bin

dev

etc

home

# 现在后面加 -l 进行测试

[root@weifeng dockerfile]# docker run bd8100b2acff -l

# 结果 我们的追加命令 是直接ENTRYPOINT 命令下的

total 56

drwxr-xr-x 1 root root 4096 May 18 02:02 .

drwxr-xr-x 1 root root 4096 May 18 02:02 ..

-rwxr-xr-x 1 root root 0 May 18 02:02 .dockerenv

lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin

drwxr-xr-x 5 root root 340 May 18 02:02 dev

drwxr-xr-x 1 root root 4096 May 18 02:02 etc

drwxr-xr-x 2 root root 4096 May 11 2019 home

lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib

Dockerfile 中很多命令都十分相似,我们需要了解它们的区别,我们最好的学习就是对比他们然后测试效果!

5.5 实战: Tomcat镜像

  1. 准备镜像文件tomcat压缩包,jdk的压缩包!
    img
  2. 编写dockerfile文件,官方命名 Dockerfile ,build 就会自动寻找这个文件,就不需要-f 指定docker file 文件路径

FROM centos

MAINTAINER weifeng1783246945@qq.com

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u241-linux-x64.tar.gz /usr/local/

ADD apache-tomcat-9.0.35.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local

WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_241

ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV CATALTNA_HOME /usr/local/apache-tomcat-9.0.35

ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35

ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALTNA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/bin/logs/catalina.out

  1. 执行构建

[root@weifeng tomcat]# docker build -t diytomcat .

  1. img
    img
  2. 运行

[root@weifeng tomcat]# docker run -d -p 9090:8080 --name mytomcat -v /home/cao/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/cao/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs diytomcat

img

  1. 进入运行中的容器 访问测试

[root@weifeng tomcat]# docker exec -it 5605928525ea /bin/bash

  1. img
  2. 发布项目

因为之前挂载了 所以此时只要把文件 放到 挂载目录 就可以实时 发布了

容器外

img

容器内

img

访问后 发现可以访问

我们以后开发的步骤:需要掌握DockerFile的编写! 我们之后的一切都是使用docker镜像来发布运行!

5.6发布自己的镜像

5.6.1 发布到DOckerHub

  1. 地址 https://hub.docker.com/
    (需要自己注册个账号)
  2. 确定这个账号可以登陆
  3. 在我们服务器上提交自己的镜像
  4. 通过命令行登陆
    img

docker login -u (用户名)

#回车后输入密码

  1. img
  2. 提交镜像

# docker push <作者>/<镜像名>:版本号

[root@weifeng ~]# docker push weifeng/diytomcat:1.0

#出现问题

The push refers to repository [docker.io/weifeng/diytomcat]

An image does not exist locally with the tag: weifeng/diytomcat

# 原因及解决 当前镜像没有版本

# docker tag 镜像id <作者用户名>/<镜像>:版本号

[root@weifeng ~]# docker push 用户名/tomcat:1.0

  1. img
    提交的时候也是按照镜像的层级进行提交

5.6.2发布阿里云镜像

  1. 登陆阿里云
  2. 找到容器镜像服务
  3. 创建命名空间 点击创建就可以了(注意一个账户只能创建三个命名空间)
    img
  4. 创建镜像仓库 点击创建镜像仓库 一步一步创建即可
    img
    填写完信息记得选本地仓库
    img
    这就是创建成功
    img
    示例
    img
    根据步骤一步一步来即可
    主要参考官方文档

小结

img

6. Docker网络

6.1 理解网络Docker0网络

清空所有环境

测试

img

三个网络

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

img

[root@weifeng ~]# docker run -d -P --name tomcat01 tomcat

# 启动容器 查看容器内部的网络地址 ip addr

[root@weifeng ~]# docker exec -it tomcat01 ip addr

# 发现容器启动的时候得到一个 eth0@if55 地址 ,docker分配的

[root@weifeng ~]# ping 172.17.0.2

# 发现可以ping 通docker容器内部

img

原理

1.我们每启动一个docker容器 ,docker 就会给docker容器分配一个ip 我们只要安装了docker,就会有一个网卡docker0

桥接模式, 使用的技术是 evth-pair技术

再次测试ip addr 发现多了一个网卡

img

  1. 在启动一个tomcat02 发现有多了一对网卡

img

# 我们发现这个容器带来的网卡 都是一对一对的

# evth-pair 就是一对的虚拟设备接口,他们都是成对成对出现的,一端连接协议,一端彼此连接

# 正因为有这个特性, evth-pair 充当一个桥梁,连接各种虚拟网络设备

# OpenStac Docker 容器之间的连接,OVS 的连接 都是使用evth-pair 技术

  1. 我们测试下 tomcat01 和 tomcat02 可不可以ping通
    img
    结论 : 容器和容器之间是可以ping通的
    img
    结论: tomcat01 和 tomcat02 是公用的一个路由器,docker0
    所有的容器不指定网络的情况下,都是docker0路由,docker会给我们的容器分配一个默认的可用IP
    docker使用的是Linux的桥接,宿主机中是一个docker的网桥 docker0 (最多可以分配65535个)
    img
    Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高!
    (比如: 内网传递)
    只有容器删除,对应的一对网桥就没了!
    img

思考一个场景,我们编写了一个微服务,database url=ip , 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来访问容器?

[root@weifeng ~]# docker exec -it tomcat02 ping tomcat01

ping: tomcat01: Name or service not known

#如何可以解决呢?

#docker run -d -P --name tomcat03 --link tomcat02 tomcat

#docker exec -it tomcat03 ping tomcat02

64 bytes from tomcat02 (172.17.0.3): icmp_seq=53 ttl=64 time=0.091 ms

64 bytes from tomcat02 (172.17.0.3): icmp_seq=54 ttl=64 time=0.091 ms

64 bytes from tomcat02 (172.17.0.3): icmp_seq=55 ttl=64 time=0.095 ms

64 bytes from tomcat02 (172.17.0.3): icmp_seq=56 ttl=64 time=0.086 ms

64 bytes from tomcat02 (172.17.0.3): icmp_seq=57 ttl=64 time=0.091 ms

64 bytes from tomcat02 (172.17.0.3): icmp_seq=58 ttl=64 time=0.085 ms

#反向可以ping通吗?

[root@weifeng ~]# docker exec -it tomcat2 ping tomcat03

Error: No such container: tomcat2

[root@weifeng ~]#

#

探究

# 列出docker网络ip

docker network ls

# 查看name是brige的元数据 docker network inspect networkID

docker network inspect 08f69d91fc03

img

其实这个tomcat03就是在本地配置了tomcat02的配置

img

本质探究: --link 就是我们hosts配置中增加了一个 172.17.0.4 tomcat02 的映射

我们现在玩Docker 已经不建议使用docker0!

docker0问题 : 它不支持容器名连接访问!

6.3 自定义网络

查看所有的docker网络

[root@weifeng ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

08f69d91fc03 bridge bridge local

f1d04511057a host host local

99e79746af60 none null local

网络模式

bridge : 桥接 docker

none : 不配置网络

host : 和宿主机共享网络

container: 容器网络连接联通!(用的少,局限大!)

测试

# 把之前的容器都删掉 净化网络环境

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

# 查看网络

[root@weifeng ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

08f69d91fc03 bridge bridge local

f1d04511057a host host local

99e79746af60 none null local

#我们之间启动的命令 默认有 --net bridge 这个就是我们的docker0

[root@weifeng ~]# docker run -d -P --name tomcat01 - tomcat

[root@weifeng ~]# docker run -d -P --name tomcat01 --net bridge tomcat

#docker 特点 , 默认 ,域名不能访问 --link 可以打通容器

#我们可以自定义一个网卡 自定义一个网络

# --driver bridge

# --subnet 192.168.0.0/16

# --gateway 192.168.0.1

[root@weifeng ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

1c058a8b2e667f10b51a61a2639e15da2904073240e10538eb206ac6b7501d68

[root@weifeng ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

08f69d91fc03 bridge bridge local

f1d04511057a host host local

1c058a8b2e66 mynet bridge local

99e79746af60 none null local

# 查看自己创建的网络元数据

docker network inspect mynet

img

# 用自己创建的网络运行tomcat容器

[root@weifeng ~]# docker run -d -P --name tomcat01 --net mynet tomcat

[root@weifeng ~]# docker run -d -P --name tomcat02 --net mynet tomcat

img

#再次测试 现在不使用--link 也可以ping名字了

[root@weifeng ~]# docker exec -it tomcat01 ping tomcat02

PING tomcat02 (192.168.0.3) 56(84) bytes of data.

64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.088 ms

64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.099 ms

64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.085 ms

64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.092 ms

64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=5 ttl=64 time=0.093 ms

我们自定义的网络docker 都已经帮我们维护了对应的关系,推荐我们平时这样使用网络!

好处:

redis : 不同的集群使用不同的网络,保证集群是安全和健康的

mysql: 不同的集群使用不同的网络,保证集群是安全和健康的

6.4 网络联通

img

img

#测试打通 tomcat01 和 1

[root@weifeng ~]# docker network connect mynet tomcat1

#查看元数据

[root@weifeng ~]# docker network inspect mynet

#连通后就是将tomcat01 放到了mynet网络下

img

img

结论 : 假设要跨网络操作别人,就需要使用docekr network connect 连通 !

6.5 部署Redis集群

img

#shell脚本

#创建网卡

docker network create redis --subnet 172.38.0.0/16

# 创建六个节点

for port in $(seq 1 6);\

do \

mkdir -p /mydata/redis/node-$/conf

touch /mydata/redis/node-$/conf/redis.conf

cat </mydata/redis/node-$/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$

cluster-announce-port 6379

cluster-announce-bus-port 16379

appendonly yes

EOF

done

# 启动

[root@weifeng ~]#

# 一次性启动

docker run -p 637$:6379 -p 1637$:16379 --name redis-$ \

-v /mydata/redis/node-$/data:/data \

-v /mydata/redis/node-$/conf/redis.conf:/etc/redis/redis.comf \

-d --net redis --ip 172.38.0.1$ redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf: \

# 一个一个启动

# 开启1

docker run -p 6371:6379 -p 16371:16379 --name redis-1 -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -v /mydata/redis/node-1/data:/data -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

# 开启2

docker run -p 6372:6379 -p 16372:16379 --name redis-2 -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -v /mydata/redis/node-2/data:/data -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

# 开启3 这个只要把外面的端口改下就好 比如 6372:6379 改为 6373:6379 把涉及的改掉即可

docker run -p 6373:6379 -p 16373:16379 --name redis-3 -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf -v /mydata/redis/node-3/data:/data -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

# 后面的依次类推即可

#进入rdis-1 创建集群

redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.3

8.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

docker搭建redis集群完成!

img

使用docker之后,所有的技术都会变得简单

6.6 spirng boot 微服务打包成Docker镜像

  1. 构建spring boot项目
  2. 打包应用
  3. 编写dockerfile
  4. 构建镜像
  5. 发布运行

以后我们使用了Docker之后,给别人交付的就是一个镜像即可!

7 Docker Compost

8 Docker Swarm

9 CI/CD 之Jenkins

0

评论区