天天看点

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

文章目录

  • 1. Docker安装
    • 1.1 Docker的基本组成
    • 1.2 安装Dokcer
    • 1.3 卸载docker
    • 1.4 阿里云镜像加速
    • 1.5 run流程
    • 1.6 底层原理
  • 2. Docker常用命令
    • 2.1 帮助命令
    • 2.2 镜像命令
      • 2.2.1 docker images查看所有本地的主机上的镜像
      • 2.2.2 docker search 搜索镜像
      • 2.2.3 docker pull 下载镜像
      • 2.2.4 docker rmi 删除镜像
    • 2.3 容器命令
      • 2.3.1 新建容器并启动 run
      • 2.3.2 docker ps 列出所有运行的容器
      • 2.3.3 退出容器
      • 2.3.4 删除容器 rm
      • 2.3.5 启动和停止容器的操作
    • 2.4 常用其他命令
      • 2.4.1 后台启动容器
      • 2.4.2 查看日志
      • 2.4.3 查看容器中进程信息 ps
      • 2.4.4 查看镜像的元数据 inspect
      • 2.4.5 进入当前正在运行的容器 exec attach
      • 2.4.6 从容器内拷贝文件到主机上
    • 2.5 常用命令小结
  • 3. 作业练习
    • 3.1 部署Nginx
      • **端口暴露的概念**
    • 3.2 docker来装一个tomcat
    • 3.3 部署es+kibana
  • 4.Portainer可视化面板
  • 5. Docker镜像讲解
    • 5.1 镜像是什么
      • 5.1.1如何得到镜像:
    • 5.2 docker镜像加载原理
      • 5.2.1 UnionFS(联合文件系统)
      • 5.2.2 docker镜像加载原理
      • 5.2.3 分层理解
        • **为什么要采用分层结构?**
        • **查看镜像分层的方式**
        • 特点
    • 5.2.4 commit镜像
  • 6. 容器数据卷
    • 6.1 什么是容器数据卷
      • 6.1.1 总结:
      • 6.1.2 使用数据卷
        • 方式一:直接使用命令来挂载 -v
    • 6.2 实战:安装MySQL
      • 6.2.1 思考:MySQL 数据持久化问题
      • 6.2.2 假设我们将容器删除
    • 6.3 具名和匿名挂载
      • 6.3.1拓展
    • 6.4初始Dockerfile
    • 6.5 数据卷容器
      • 结论
  • 7. DockerFile
    • 7.1 构建步骤
    • 7.2 Dockerfile构建过程
      • 7.2.1 基础知识:
    • 7.3 Dockerfile指令
    • 7.4 实战测试
      • 7.4.1 创建一个自己的centos
      • 7.4.2 CMD和ENTRYPOINT的区别
        • 测试CMD
        • 测试ENTRYPOINT
    • 7.5 实战测试:Tomcat镜像
    • 7.6 发布镜像
      • 7.6.1 DcokerHub
      • 7.6.2 阿里云
    • 7.7 docker流程小结
  • 8. Docker网络
    • 8.1 理解Docker0
      • 8.1.1 原理
      • 8.1.2 小结
    • 8.2 容器互联 --link
    • 8.3 自定义网络
      • 好处:
    • 8.4 网络连通
    • 8.5 实战:部署Redis集群

1. Docker安装

1.1 Docker的基本组成

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

镜像(image):

​ docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像------>run------->tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)

容器(container):

​ Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的

​ 启动,停止,删除,基本命令

​ 目前可以把容器理解为一个简易的Linux系统

仓库(repository):

​ 仓库就是存放镜像的地方

​ 仓库分为公有仓库和私有仓库

​ Docker Hub

​ 阿里云等等都有容器服务器(默认在国外,配置镜像加速)

1.2 安装Dokcer

​ 环境准备
  1. 需要linux基础
  2. Centos7
  3. 使用软件进行远程连接
环境查看
# 系统内核是3.10以上的
unmae -r
           
# 系统版本
cat /etc/os-release
           
安装

帮助文档

# 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 \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
# 更新yum软件包索引
yum makecache fast

# 4. 安装docker相关的   docker-ce 社区版 ee企业版
yum install docker-ce docker-ce-cli containerd.io

# 5.启动docker
systemctl start docker

# 6.使用docker version测试是否安装成功
docker version

# 7.hello-word
docker run hello-word

# 8.查看下载的这个hello-word镜像
docker images
           

1.3 卸载docker

# 1.卸载依赖
yum remove docker-ce docker-ce-cli containerd.io

# 2.删除资源
rm -rf /var/lib/docker

#/var/lib/docker docker的默认工作路径
           

1.4 阿里云镜像加速

  1. 登录阿里云找到容器服务
  2. 找到镜像加速的地址
  3. 配置应用
    mkdir -p /etc/docker
    # 编辑daemon.json
    tee /etc/docker/daemon.json <<-'EOF'
    # 设置加速器地址
    {
      "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"]
    }
    EOF
    # 最后重新加载和重启docker:
    systemctl daemon-reload
    
    systemctl restart docker
               
    mkdir -p /etc/docker
    tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://me0kxh75.mirror.aliyuncs.com"]
    }
    EOF
    systemctl daemon-reload
    systemctl restart docker
               

1.5 run流程

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

1.6 底层原理

docker是怎么工作的?

Docker 是一个client-server 结构的系统,Docker的守护进程运行在主机上,通告Socker从客户端访问

Dokcer server 接收到Docker-client 的指令,就会执行这个命令

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

Docker为什么比虚拟机快

  • Docker有着比虚拟机更少的抽象层
  • Docker 利用的是宿主机的内核,VM需要Guest OS
  • 所以,新建一个容器的时候,Docker不需要虚拟机一样重新加载一个操作系统的内核,避免引导。虚拟机是加载Guest OS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

2. Docker常用命令

2.1 帮助命令

docker version    # 显示docker的版本信息
docker info       # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help   #万能命令
           

2.2 镜像命令

2.2.1 docker images查看所有本地的主机上的镜像

docker images

# 解释
REPOSITORY  镜像的仓库源
TAG			镜像的标签
IMAGE ID	镜像的ID
CREATED		镜像的创建时间
SIZE		镜像的大小

# 可选项
-a  # 列出所有的镜像
-q  # 只显示镜像的ID
           

2.2.2 docker search 搜索镜像

docker search mysql

# 可选项
--filter=STARS=3000   #搜索出来的镜像是STARS大于3000的
           

2.2.3 docker pull 下载镜像

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

如果不写tag,默认就是latest
分层下载,docker image的核心,联合文件系统
Digest #签名
docker.io/library/mysql:latest  #真实地址

#等价于他
docker pull mysql
docker pull docker.io/library/mysql:latest

# 指定版本下载
docker pull mysql:5.7
           

2.2.4 docker rmi 删除镜像

docket rmi -f 镜像id  #删除指定镜像
docket rmi -f 镜像id 镜像id  #删除多个镜像
docket rmi -f $(docker images -aq)  #递归删除所有镜像
           

2.3 容器命令

说明:我们有了镜像才可以创建容器,Linux,下载一个centos 镜像来测试学习

docker pull centos
           

2.3.1 新建容器并启动 run

docker run [可选参数] image

# 参数说明
--name="Name"   # 容器名字  tomcat01 tomcat02,用来区分容器
-d				# 后台方式运行
-it 				# 使用交互方式运行,进入容器查看内容
-p				# 指定容器的端口 -p 8080:8080
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口(常用)
	-p 容器端口
	容器端口
-p				# 随机指定端口

# 测试
docker run -it centos /bin/bash  # 启动并进入容器
	exit # 从容器中退回到主机
           

2.3.2 docker ps 列出所有运行的容器

docker ps  # 列出当前正在运行的容器

-a  # 列出当前正在运行的容器+历史运行过的容器
-n=?  # 显示最近创建的容器,例如-n=1,显示最近创建的一个容器
-q  # 只显示容器的编号
           

2.3.3 退出容器

exit   # 直接容器停止并退出
ctrl+p+q  #容器不停止退出
           

2.3.4 删除容器 rm

docker rm 容器id   		#删除指定的容器,不能删除正在运行的容器,如果想要强制删除 rm -f
docker rm -f $(docker ps -aq)  #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器
           

2.3.5 启动和停止容器的操作

docker start 容器id         # 启动容器
docker restart 容器id		  # 重启容器
docker stop 容器id		  # 停止当前正在运行的容器
docker kill 容器id		  # 强制停止当前容器
           

2.4 常用其他命令

2.4.1 后台启动容器

# 命令 docker run -d 镜像名
docker run -d centos

# 问题 docker ps 发现centos停止了

# 常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
           

2.4.2 查看日志

docker logs 
# 显示日志
-tf   #显示全部日志
--tail number #显示指定数量的日志

docker logs -f -t --tail 容器id   # 没有日志

#自己编写一段shell脚本
docker run -d centos /bin/bash -c "while true;do echo zjc;sleep 1;done"

docker logs -tf --tail 10 容器id   
           

2.4.3 查看容器中进程信息 ps

2.4.4 查看镜像的元数据 inspect

docker inspect 容器id
           

2.4.5 进入当前正在运行的容器 exec attach

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

#命令
# 方式一
docker exec -it 容器id /bin/bash

# 方式二xi
docker attach 容器id

#区别
docker exec #进入容器之后开启一个新的终端,可以在里面操作(常用)
docker attach # 进入容器正在执行的终端,不会启动新的进程
           

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

docker cp 容器id:容器内路径 目的地主机路径
#拷贝是一个手动过程,可以使用-v卷的技术,可以实现
           

2.5 常用命令小结

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
attach					# 当前shell下attach连接指定运行镜像
build					# 通过dockerfile定制镜像
commit					# 提交当前容器为新的镜像
cp						# 从容器中拷贝指定文件或者目录到宿主机中
create					# 创建一个新的容器,同run 但不启动容器
diff					# 查看docker 容器变化
events					# 从docker 服务获取容器实时事件
exec					# 在已存在的容器上运行命令
export					# 导出容器的内容作为一个 tar 归档文件[对应import]
history					# 展示一个镜像形成历史
images					# 列出系统当前镜像
import        			# 从tar包中的内容创建一个新的文件系统映像[对应export]
info					# 显示系统相关信息
inspect					# 查看容器详细信息
kill					# kill 指定容器
load					# 从一个tar 包中加载一个镜像[对应save]
login 					# 注册或者登陆一个docker源服务器
logout					# 从当前docker registry退出
logs					# 输出当前容器日志信息
port					# 查看映射端口对应的容器内部源端口
pause     				# 暂停容器
ps						# 列出容器列表
pull					# 从docker镜像源服务器拉取指定镜像或者库镜像
push					# 推送指定镜像或者库镜像至docker源服务器
restart					# 重启运行的容器
rm						# 移除一个或者多个容器
rmi						# 移除一个或多个镜像[无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除]
run 					# 创建一个新的容器并运行一个命令
save					# 保存一个镜像为一个tar包[对应load]
search					# 在docker hub 中搜索镜像
start 					# 启动容器
stop					# 停止容器
tag						# 给源中镜像打标签
top						# 查看容器中运行的进程信息
unpause					# 取消暂停容器
version					# 查看docker版本号
wait					# 截取容器停止时的退出状态值
           

3. 作业练习

3.1 部署Nginx

# 1.搜索镜像 search,可以去docker 搜索,可以看到帮助文档
# 2.下载镜像 pull
# 3.运行测试
docker images 

# -d 后台运行
# --name 给容器命名
# -p 宿主机端口,容器内部端口
docker run -d --name nginx01 -p 3344:80 nginx
docker ps
curl localhost:3344

# 进入容器
docker exec -it nginx01 /bin/bash

docker stop 容器id


# 思考问题:我们每次改动nginx配置文件,都需要进入容器内部,十分麻烦,我们可以在容器外部提供一个映射路径,到达在容器外部修改文件,容器内部就可以自动修改   -v 数据卷技术
           

端口暴露的概念

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

3.2 docker来装一个tomcat

# 官方的使用
docker run -it --rm tomcat:9.0   # 用完就删除

# 我们之前的启动都是后台,停止容器之后,容器还是可以查看到,docker run -it --rm tomcat:9.0

# 下载再启动
docker pull tomcat

# 启动运行
docker run -d -p 3355:8080 --name tomcat101 tomcat

# 测试访问没有问题

# 进入容器
docker exec -it tomcat101 /bin/bash

# 发现问题:1. linux命令少了  2. 没有webapps
# 阿里云镜像的原因,默认是最小的镜像,所有不必要的都删除掉,保证最小可运行的环境
  
思考:在容器外部提供给一个映射路径,webapps,我们在外部防止项目,就自动同步到内部就好了
           

3.3 部署es+kibana

# es 暴漏的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录
# --net somenetwork? 网络配置

# 启动es
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

# 启动了linux 就卡住了,docker stats 查看CPU的状态
# 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

curl localhost:9200
           

使用kibana连接es,思考网络如何才能连接过去

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

4.Portainer可视化面板

  • portainer(先用这个)
docker run -d -p 8080:9000 \
--restart=always \-v /var/run/docker.sock:/var/run/docker.sock \--privileged=true portainer/portainer
           
  • Rancher(CI/CD再用)

什么是portainer?

  • Docker图形化界面管理工具,提供一个后台面板供我们操作
docker run -d -p 8080:9000 \
--restart=always \-v /var/run/docker.sock:/var/run/docker.sock \--privileged=true portainer/portainer
           

访问测试:http://ip:8080

5. Docker镜像讲解

5.1 镜像是什么

镜像是一种轻量级、可执行的独立软件保,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软

件所需的所有内容,包括代码、运行时库、环境变量和配置文件

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

5.1.1如何得到镜像:

  • 远程仓库下载
  • 其他人拷贝给你
  • 自己制作一个镜像dockerfile

5.2 docker镜像加载原理

5.2.1 UnionFS(联合文件系统)

**UnionFs(联合文件系统):**Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对

文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite

several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层

来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像

**特性:**一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起

来,这样最终的文件系统会包含所有底层的文件和目录

5.2.2 docker镜像加载原理

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

boots(boot file system)

主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。

这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。

当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system) 在 bootfs之上。

包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。

rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。

由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.

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

5.2.3 分层理解

为什么要采用分层结构?

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

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

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

查看镜像分层的方式

docker image inspect
           

特点

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

5.2.4 commit镜像

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

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

实战测试

# 启动一个默认的tomcat

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

# 手动拷贝进去了基本的文件

# 将修改后的容器通过commit提交为一个新的镜像,我们以后就可以使用修改过的镜像,这就是自己修改过的一个镜像
           

如果想要保存当前容器的状态,我们可以通过commit来提交,获得一个镜像,类似于虚拟机的快照

6. 容器数据卷

6.1 什么是容器数据卷

docker的理念回顾

将应用和环境打包成一个镜像

如果数据都在容器中,那么删除容器,数据就会丢失! 需求:数据可以持久化

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

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

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

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

6.1.1 总结:

​ 容器的持久化和同步操作!容器之间也是可以数据共享的

6.1.2 使用数据卷

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

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

# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash 

# 启动起来之后,我们可以通过 docker inspect 容器id 来查看元数据
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 再次测试
1. 停止容器
2. 在宿主机上修改文件
3. 再次启动容器
4. 容器内的数据依旧是同步的
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

好处:

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

6.2 实战:安装MySQL

6.2.1 思考:MySQL 数据持久化问题

# 获取镜像
docker pull mysql:5.7

# 运行容器,数据挂载   # 安装启动mysql,需要配置密码!!!
# 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 运行容器,数据挂载   # 安装启动mysql,需要配置密码!!!
-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 --name mysql01 mysql:5.7

# 启动成功之后,我们在本地使用sql yog测试连接
# sqlyog 连接到服务器的3310 --- 3310和容器内的3306映射,这个时候就可以连接上了

# 在本地测试创建一个数据库,查看一下我们映射的路径是否OK
           

6.2.2 假设我们将容器删除

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能

6.3 具名和匿名挂载

# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
➜  ~ docker volume ls    
DRIVER              VOLUME NAME
local               33ae588fae6d34f511a769948f0d3d123c9d45c442ac7728cb85599c2657e50d        
# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径!

# 具名挂载
➜  ~ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
➜  ~ docker volume ls                  
DRIVER              VOLUME NAME
local               juming-nginx

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

# 查看一下这个卷
docker volume inspect juming-nginx

# 所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data,如果指定了目录,docker volume ls 是查看不到的
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的是具名挂载

# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径			#匿名挂载
-v 卷名:容器内路径		#具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
           

6.3.1拓展

# 通过 -v 容器内路径:ro rw 改变读写权限
ro #read only 只读
rw #read write 可读可写

# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx

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

6.4初始Dockerfile

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

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

# 创建一个dockerfile文件,名字可以随便 建议Dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "----end----"
CMD /bin/bash
#这里的每个命令,就是镜像的一层!

docker build -f /dockerfile -t kuangshen/centos:v1.0 .
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

这个卷和外部有一个同步的目录

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

查看一下挂载的路径

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

测试一下刚才的文件是否同步

这种方式之后使用的很多,因为 通常我们会构建自己的镜像

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

6.5 数据卷容器

多个mysql同步数据

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 启动三个容器,通过我们自己写的容器
docker run -it --name docker01 kuangshen/centos:1.0
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 此时删除容器docker01,docker02和docker03依旧可以访问这个文件
拷贝的概念
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

多个mysql实现数据共享

docker run -d -p 3306:3306 -v /etc/mysql/conf.d  -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7
# 这个时候,可以实现两个容器数据同步!
           

结论

  • 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
  • 但是一旦持久化到了本地,这个时候本地的数据是不会删除的

7. DockerFile

dockerfile是用来构建docker镜像的文件,命令参数脚本

7.1 构建步骤

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

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

7.2 Dockerfile构建过程

7.2.1 基础知识:

  1. 每个保留关键字(指令)都必须是大写字母
  2. 从上到下顺序执行
  3. 表示注释(#)
  4. 每个指令都会创建提交一个新的镜像,并提交
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

Dockerfile是面向开发的,以后发布项目,做镜像,就需要编写dockerfile文件

Docker镜像逐渐成为企业交付的标准

Dockerfile:构建文件,定义了一切的步骤,源代码

Dockerimages:通告Dockerfile构建生成的镜像,最终发布运行的产品

Docker容器:容器就是镜像运行起来提供服务

7.3 Dockerfile指令

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
FROM              # 基础镜像,一切从这开始构建
MAINTAINER 		  # 镜像是谁写的,姓名+邮箱
RUN				  # 镜像构建的时候需要运行的命令
ADD				  # 添加内容
WORKDIR			  # 镜像的工作命令
VOLUME     		  # 挂载的目录
EXPOSE			  # 指定暴露端口		  
CMD				  # 指定容器启动的时候运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT        # 指定这个容器启动的时候要运行的命令可以追加命令
ONBUILD			  # 当构建一个被继承的 dockerfile ,这个时候就会运行ONBUILD的指令,触发指令
COPY              # 类似ADD,将我们的文件拷贝到镜像中
ENV				  # 构建的时候设置环境变量
           

7.4 实战测试

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

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

7.4.1 创建一个自己的centos

# 1.编写Dcokerfile文件
vim mydockerfile-centos

FROM centos
MAINTAINER zhaojinchao<[email protected]>

ENV MYPATH /usr/loacl
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:0.1 .

# 3.测试运行
           

我们可以通过 docker history+镜像id 列出本地镜像的变更历史

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

7.4.2 CMD和ENTRYPOINT的区别

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

测试CMD

# 编写dockerfile文件
vi dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]

# 构建镜像
docker build -f dockerfile-cmd-test -t cmdtest .

# RUN运行,发现我们的ls -a命令生效
docker run dd8e4401d72f

# 想追加一个命令 -l,成为ls -al
docker run dd8e4401d72f -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.
ERRO[0000] error waiting for container: context canceled 
# cmd的情况下 -l 替换了CMD["ls","-l"]。 -l  不是命令所有报错
           

测试ENTRYPOINT

# 编写dockerfile文件
$ vim dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]

$ docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .

$ docker run 3c4c9621ed91   
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found ...

# 我们的命令,是直接拼接在我们得ENTRYPOINT命令后面的
$ docker run entrypoint-test:0.1 -l
total 56
drwxr-xr-x   1 root root 4096 May 16 06:32 .
drwxr-xr-x   1 root root 4096 May 16 06:32 ..
-rwxr-xr-x   1 root root    0 May 16 06:32 .dockerenv
lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root  340 May 16 06:32 dev
drwxr-xr-x   1 root root 4096 May 16 06:32 etc
drwxr-xr-x   2 root root 4096 May 11  2019 home
lrwxrwxrwx   1 root root    7 May 11  2019 lib -> usr/lib
lrwxrwxrwx   1 root root    9 May 11  2019 lib64 -> usr/lib64 ....
           

7.5 实战测试:Tomcat镜像

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

FROM centos 
MAINTAINER chao      # 名字

COPY readme.txt /usr/local/readme.txt #复制文件

ADD jdk-8u231-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_11 #设置环境变量
ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar #设置环境变量 分隔符是:
ENV CATALINA_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:$CATALINA_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 # 设置默认命令

3. 构建镜像
docker build -t diytomcat .

4. 运行
$ docker run -d -p 9090:8080 --name kuangshentomcat -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs diytomcat

5、访问测试

6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
           
  1. 发布项目
vi web.xml 

  <?xml version="1.0" encoding="UTF-8"?>
  <web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

  </web-app>
           
vi index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JC</title>
</head>
<body>
Hello World!<br/>
<%
sysem.out.println("---my test web logs---")
%>
</body>
</html>
           

7.6 发布镜像

提交的时候也是按照镜像的层级来进行提交的

7.6.1 DcokerHub

  1. https://hub.docker.com 注册自己的账号
  2. 确定这个账号可以登录
  3. 在我们服务器上提交自己的镜像
  4. 登录完毕之后就可以提交镜像了,docker push
$ 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

# 登录
dokcer login -u 用户名

# 上传镜像
docker push 镜像名

# push镜像的问题
 会发现push不上去,因为如果没有前缀的话默认是push到 官方的library
# 解决方法
1. 第一种 build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
$ docker build -t chengcoder/mytomcat:0.1 .

2. 第二种 使用docker tag 然后再次push
$ docker tag 镜像id chengcoder/mytomcat:1.0 #然后再次push
           

7.6.2 阿里云

  1. 登录阿里云
  2. 找到容器镜像服务
  3. 创建命名空间
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  1. 创建容器镜像
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  1. 浏览阿里云
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

阿里云容器镜像的就参考官方地址

7.7 docker流程小结

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

8. Docker网络

8.1 理解Docker0

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

三个网络

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 测试  运行一个tomcat
docker run -d -P --name tomcat01 tomcat

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

       
docker exec -it 容器id ip addr

# 查看容器内部网络地址 发现容器启动的时候会得到一个 [email protected] ip地址,docker分配!
550: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
       
# 思考? linux能不能ping通容器内部! 可以 容器内部可以ping通外界吗? 可以!
$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms
           

8.1.1 原理

  • 我们每启动一个docker容器,docker就会给docker容器分配一个ip ,我们只要安装了docker,就会有一个网卡docker0 桥接模式,使用的技术是 evth-pair技术
  1. 再次测试ip addr
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  1. 再启动一个容器测试,发现又多了一对网卡
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 我们发现这个容器带来的网卡,都是一对一对出现的
# evth-pair 就是一对的虚拟设备接口,都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# Openstack,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
           
  1. 我们测试 tomcat01 和 tomcat02 可以ping通
docker exec -it tomcat02 ping 172.18.0.2

# 结论:容器和容器之间是可以相互ping通的
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

结论: tomcat01 和 tomcat02 是共用的一个 docker0

所有的容器不指定网络的情况下,都是通过docker0通信的,docker会给我们的容器分配一个默认的可用IP

8.1.2 小结

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  • Docker使用的是Linux的桥接,宿主机中是一个Dokcer容器的网桥 docker0
  • Dcoker中的所有的网络接口都是虚拟的,虚拟的转发效率高
  • 只要容器删除,对应网桥一对就都没了
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

8.2 容器互联 --link

场景:编写了一个微服务,项目不重启,数据库 IP 换掉了,如何用名字来进行访问容器
$ docker exec -it tomcat02 ping tomca01   # ping不通
ping: tomca01: Name or service not known
# 如何解决?
通过 --link 解决了网络连通问题


# 运行一个tomcat03 --link tomcat02 
$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef

# 用tomcat03 ping tomcat02 可以ping通
$ docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.115 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms

# 用tomcat02 ping tomcat03 ping不通


           

探究:inspect

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  • –link 就是在我们hosts配置中增加了一个 172.18.0.3 tomcat02 312857784cd4
  • 现在已经不建议使用 --link 了

docker0的问题:不支持容器名连接网络

8.3 自定义网络

查看所有的docker 网络

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络

网络模式:

1.	bridge:桥接(默认)

2.	none:不配置网络
3.	host:和宿主机共享网络
4.	container:容器网络互通(用的少,局限大)
           

测试:

# 我们直接启动的命令默认有--net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
等价于---> docker run -d -P --name tomcat01 --net bridge tomcat

# docker0 特点:默认bridge,域名不能访问,  --link可以打通连接,但不推荐使用

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

自定义一个网络

# --driver  bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

docker network ls

# 我们的网络就创建好了
docker network inspect mynet

# 测试
docker run -d -P --name tomcat-net-01 --network mynet tomcat
docker run -d -P --name tomcat-net-02 --network mynet tomcat


# 自定义的网络可以直接ping 通, 不需要使用 --link
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  • 自定义的网络 docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络

好处:

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

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

8.4 网络连通

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 测试打通 tomcat01 - mynet
docker network connect mynet tomcat01

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

# 一个容器两个ip地址
           
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
  • 结论:假设要跨网络操作别人,就需要使用docker network connect 连通

8.5 实战:部署Redis集群

Docker笔记1. Docker安装2. Docker常用命令3. 作业练习4.Portainer可视化面板5. Docker镜像讲解6. 容器数据卷7. DockerFile8. Docker网络
# 创建网卡
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

# 通过脚本运行六个redis
for port in $(seq 1 6);\
docker run -p 637${port}:6379 -p 1667${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


docker exec -it redis-1 /bin/sh #redis默认没有bash

# 创建集群
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