2023最强Docker教程

一、基本概念

1、Docker架构

在这里插入图片描述

K8S:CRI(Container Runtime Interface)

Client: 客户端;操作docker服务器的客户端(命令行或者界面)

Docker_Host:Docker主机;安装Docker服务的主机

Docker_Daemon:后台进程;运行在Docker服务器的后台进程

Containers:容器;在Docker服务器中的容器(一个容器一般是一个应用实例,容器间互相隔离)

Images:镜像、映像、程序包;Image是只读模板,其中包含创建Docker容器的说明。容器是由Image运

行而来,Image固定不变。

Registries:仓库;存储Docker Image的地方。官方远程仓库地址: https://hub.docker.com/search

Docker用Go编程语言编写,并利用Linux内核的多种功能来交付其功能。 Docker使用一种称为名称

空间的技术来提供容器的隔离工作区。 运行容器时,Docker会为该容器创建一组名称空间。 这些

名称空间提供了一层隔离。 容器的每个方面都在单独的名称空间中运行,并且对其的访问仅限于

该名称空间。

Docker面向对象
镜像(Image)
容器(Container)对象(实例)

容器与虚拟机

在这里插入图片描述

2、Docker隔离原理

  • namespace 6 项隔离 (资源隔离)
namespace系统调用参数隔离内容
UTSCLONE_NEWUTS主机和域名
IPCCLONE_NEWIPC信号量、消息队列和共享内存
PIDCLONE_NEWPID进程编号
NetworkCLONE_NEWNET网络设备、网络栈、端口等
MountCLONE_NEWNS挂载点(文件系统)
UserCLONE_NEWUSER用户和用户组
  • cgroups 资源限制 (资源限制)

cgroup提供的主要功能如下:

    • 资源限制:限制任务使用的资源总额,并在超过这个 配额 时发出提示
    • 优先级分配:分配CPU时间片数量及磁盘IO带宽大小、控制任务运行的优先级
    • 资源统计:统计系统资源使用量,如CPU使用时长、内存用量等
    • 任务控制:对任务执行挂起、恢复等操作

cgroup资源控制系统,每种子系统独立地控制一种资源。功能如下

子系统功能
cpu使用调度程序控制任务对CPU的使用
cpuacct(CPU Accounting)自动生成cgroup中任务对CPU资源使用情况的报告
cpuset为cgroup中的任务分配独立的CPU(多处理器系统时)和内存
devices开启或关闭cgroup中任务对设备的访问
freezer挂起或恢复cgroup中的任务
memory设定cgroup中任务对内存使用量的限定,并生成这些任务对内存资源使用情况的报告
perf_event(Linux CPU性能探测器)使cgroup中的任务可以进行统一的性能测试
net_cls(Docker未使用)通过等级识别符标记网络数据包,从而允许Linux流量监控程序(Tra?icController)识别从具体cgroup中生成的数据包

3、 Docker 如何工作?

​ Docker 技术使用 Linux 内核和内核功能(例如 Cgroups 和 namespaces)来分隔进程,以便各进程相互独立运行。这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用程序,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。

​ 容器工具(包括 Docker)可提供基于镜像的部署模式。这使得它能够轻松跨多种环境,与其依赖程序共享应用或服务组。Docker 还可在这一容器环境中自动部署应用程序(或者合并多种流程,以构建单个应用程序)。

4、Docker安装

以下以centos为例;

更多其他安装方式,详细参照文档: https://docs.docker.com/engine/install/centos/

1、移除旧版本

sudo yum remove docker*

2、设置docker yum源

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

3、安装最新docker engine (可不安装)

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

4、安装指定版本docker engine

1、在线安装
#找到所有可用docker版本列表
yum list docker-ce --showduplicates | sort -r
# 安装指定版本,用上面的版本号替换<VERSION_STRING>
#sudo yum install docker-ce-<VERSION_STRING>.x86_64 docker-ce-cli-<VERSION_STRING>.x86_64 containerd.io
#例如
yum install -y docker-ce-19.03.9  docker-ce-cli-19.03.9 containerd.io
2、离线安装
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
rpm -ivh xxx.rpm
可以下载 tar
解压启动即可
https://docs.docker.com/engine/install/binaries/#install-daemon-and-client-binaries-on-linux

5、启动服务

# 启动
systemctl start docker

# 开机自启
systemctl enable docker

6、镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://c9jwzg2k.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 阿里云的镜像是从docker hub来的,我们配置了加速,默认是从阿里云(缓存)下载
# 以后docker下载直接从阿里云拉取相关镜像
#/etc/docker/daemon.json 是Docker的核心配置文件。

{
    "registry-mirrors": [
        "https://mirror.ccs.tencentyun.com"
    ]
}

7、可视化界面-Portainer

1、什么是Portainer

https://documentation.portainer.io/

​ Portainer社区版2.0拥有超过50万的普通用户,是功能强大的开源工具集,可让您轻松地在Docker,Swarm,Kubernetes和Azure ACI中构建和管理容器。 Portainer的工作原理是在易于使用的GUI后面隐藏使管理容器变得困难的复杂性。通过消除用户使用CLI,编写YAML或理解清单的需求,Portainer使部署应用程序和解决问题变得如此简单,任何人都可以做到。 Portainer开发团队在这里为您的Docker之旅提供帮助;

2、安装
# 服务端部署
docker run -d -p 8000:8000 -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --name prtainer portainer/portainer

docker run -d \
-p 9000:9000 \   # portainer默认端口是9000,映射到本地9000端口,通过本地地址访问
--restart=always \  # 设置自动重启
-v /var/run/docker.sock:/var/run/docker.sock \  # 单机必须指定docker.sock
--name Prtainer portainer/portainer
# 访问 9000 端口即可
#agent端部署
docker run -d -p 9001:9001 --name portainer_agent --restart=always -v
/var/run/docker.sock:/var/run/docker.sock -v
/var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent

# 修改容器总是开机重启
docker update 容器id --restart=always

5、Docker镜像生命周期

在这里插入图片描述

二、镜像、容器

1、常见命令

所有Docker命令手册:https://docs.docker.com/engine/reference/commandline/docker/

命令作用
attach绑定到运行中容器的 标准输入, 输出,以及错误流(这样似乎也能进入容器内容,但是一定小心,他们操作的就是控制台,控制台的退出命令会生效,比如redis,nginx…)
build从一个 Dockerfile 文件构建镜像
commit把容器的改变 提交创建一个新的镜像
cp容器和本地文件系统间 复制 文件/文件夹
create创建新容器,但并不启动(注意与docker run 的区分)需要手动启动。start\stop
diff检查容器里文件系统结构的更改【A:添加文件或目录 D:文件或者目录删除 C:文件或者目录更改】
events获取服务器的实时事件
exec在运行时的容器内运行命令
export导出容器的文件系统为一个tar文件。commit是直接提交成镜像,export是导出成文件方便传输
history显示镜像的历史
images列出所有镜像
import导入tar的内容创建一个镜像,再导入进来的镜像直接启动不了容器。/docker-entrypoint.sh nginx -g ‘daemon o?;’ docker ps --no-trunc 看下之前的完整启动命令再用他
info显示系统信息
inspect获取docker对象的底层信息
kill杀死一个或者多个容器
load从 tar 文件加载镜像
login登录Docker registry
logout退出Docker registry
logs获取容器日志;容器以前在前台控制台能输出的所有内容,都可以看到
pause暂停一个或者多个容器
port列出容器的端口映射
ps列出所有容器
pull从registry下载一个image 或者repository
push给registry推送一个image或者repository
rename重命名一个容器
restart重启一个或者多个容器
rm移除一个或者多个容器
rmi移除一个或者多个镜像
run创建并启动容器
save把一个或者多个镜像保存为tar文件
search去docker hub寻找镜像
start启动一个或者多个容器
stats显示容器资源的实时使用状态
stop停止一个或者多个容器
tag给源镜像创建一个新的标签,变成新的镜像
top显示正在运行容器的进程
unpausepause的反操作
update更新一个或者多个docker容器配置
versionShow the Docker version information
container管理容器
image管理镜像
network管理网络
volume管理卷

根据正在运行的容器制作出相关的镜像:反向

根据镜像启动一个容器:正向

有了Docker:

1、先去软件市场搜镜像:https://registry.hub.docker.com/ docker hub

2、下载镜像 docker pull xxx

3、启动软件 docker run 镜像名;

对于镜像的所有管理操作都在这一个命令:docker image --help

在这里插入图片描述

1、docker ps

# 查看容器
docker ps
# 查看停止的容器
docker ps -f status=exited
# 查看所有容器(包括运行和停止)。
docker ps -a
# 查看最后一次运行的容器。
docker ps -l
# 列出最近创建的 n 个容器。
docker ps -n 5

2、docker images

# 列出所有镜像
docker images

3、docker pull

# 以redis为例
docker pull redis

# 不写标签相当于
docker pull redis:latest(最新版)

4、docker create

# 创建容器
docker create --name myredis -p 6379:6379 redis
docker create --name myredis -p 6379(主机的端口):6379(容器的端口) redis

https://docs.docker.com/engine/reference/commandline/create/

5、docker start

# 用create创建的容器要用start启动
docker start 容器名或者容器id
docker start myredis

6、docker stop

# 停止容器
docker stop 容器名或者容器id
docker stop myredis

7、docker restart

# 重启容器
docker restart 容器名或者容器id
docker restart myredis

8、docker rm

# 删除容器
docker rm 容器名或者容器id

# 强制删除
docker rm -f 容器名或者容器id

# 删除全部容器
docker rmi -f $(docker ps -aq)

9、docker rmi

# 删除镜像
docker rmi 镜像名或者镜像id

# 强制删除
docker rmi -f 镜像名或者镜像id

# 删除全部镜像
docker rmi -f $(docker images -aq)

10、docker kill

# 强制停止容器
docker kill 容器名或者容器id

11、docker port

# 查看容器端口映射
docker port 容器名或者容器id
docker port myredis

12、docker logs

# 查看容器运行日志
docker logs 容器名或者容器id
docker logs myredis

# 实时查看
docker logs -f myredis

# 查看最后100 行日志
docker logs -f -t --tail 100 myredis

# 查看最近30分钟的日志
docker logs --since 30m myredis

# 查看时间段日志
docker logs -t --since="2021-11-01" --until "2021-11-05" myredis

13、docker rename

# 重命名容器
docker rename 容器名 新容器名
docker rename myredis redis

14、docker stats

# 查看容器资源的实时使用状态
docker stats 容器名或者容器id

15、docker update

# 更新容器配置
# 更新容器为开机自启
docker update 容器名或者容器id --restart=always

16、docker tag

# 给镜像重新打标签
docker tag 原镜像:标签 新镜像名:标签 

17、docker prune

# 移除游离镜像 dangling:游离镜像(没有镜像名字的)
docker image prune

# 清理docker system
docker system prune

18、docker pause

# 暂停容器
docker pause 容器名或者容器id

19、docker unpause

# 启动已暂停的容器
docker unpause 容器名或者容器id

20、docker inspect

# 查看镜像详细信息
docker inspect 镜像id或者镜像名

# 查看容器详细信息
docker container inspect 容器名或者容器id

# network volume等等都可以查看
docker inspect image/network/volume ....

21、docker exec

# 进入容器
docker exec -it 容器名或者容器id /bin/bash

# 0用户,以特权方式进入容器
docker exec -it -u 0:0 --privileged myredis /bin/bash

https://docs.docker.com/engine/reference/commandline/exec/

22、docker attach

# 进容器 绑定的是控制台. 可能导致容器停止。不要用这个
docker attach 

23、docker export、import

# 导出镜像
docker export 导出的文件被import导入以后变成镜像,并不能直接启动容器,需要知道之前的启动命令
docker export -o nginx.tar 容器id
docker import nginx.tar mynginx:v6
(docker ps --no-trunc),然后再用下面启动。
docker run -d -P mynginx:v6 /docker-entrypoint.sh nginx -g 'daemon off;'
或者docker image inspect 看之前的镜像,把 之前镜像的 Entrypoint的所有和 Cmd的连接起来就
能得到启动命令

24、docker save、load

docker save -o busybox.tar busybox:latest 把busybox镜像保存成tar文件
docker load -i busybox.tar  把压缩包里面的内容直接导成镜像

25、docker commit

# 一般运行中的容器会常年修改,我们要使用最终的新镜像,把新的镜像放到远程docker hub,方便后来在其他机器下载
docker commit -a xueqimiao -m "first commit" mynginx4 mynginx:v4
# 会产生游离镜像

在这里插入图片描述

2、典型命令

1、docker run

  • -d: 后台运行容器,并返回容器ID
  • -i: 以交互模式运行容器,通常与 -t 同时使用
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p:指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
  • --name="nginx-lb":为容器指定一个名称
  • –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h “mars”: 指定容器的hostname;
  • -e username="ritchie": 设置环境变量
  • –env-file=[]: 从指定文件读入环境变量;
  • --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行
  • -m :设置容器使用内存最大值
  • --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型
  • –link=[]: 添加链接到另一个容器;
  • –expose=[]: 开放一个端口或一组端口;
  • --restart , 指定重启策略,可以写--restart=awlays 总是故障重启
  • --volume , -v: 绑定一个卷。一般格式 主机文件或文件夹:虚拟机文件或文件夹
1、部署Nginx
# 注意 外部的/nginx/conf下面的内容必须存在,否则挂载会覆盖
docker run --name nginx-app \
-v /app/nginx/html:/usr/share/nginx/html:ro \
-v /app/nginx/conf:/etc/nginx
-d nginx:1.20.1

# nginx目录放在/opt/docker/下

# 随便启动一个 nginx 实例,只是为了复制出配置
docker run -p 80:80 -p 443:443 --name nginx443 -d nginx:1.20.1

mkdir -p /usr/local/docker/nginx/html
mkdir -p /usr/local/docker/nginx/logs
mkdir -p /usr/local/docker/nginx/conf


# 复制到/opt/docker/temp下
docker container cp nginx:/etc/nginx /opt/docker/temp 
# 比如
docker container cp 8662e037621d:/etc/nginx /usr/local/docker/nginx/conf/

mv /usr/local/docker/nginx/conf/nginx/*  /usr/local/docker/nginx/conf

rm -rf /opt/docker/temp

docker stop nginx

docker rm $Containerid

docker run -p 80:80 --name nginx \
 -v /opt/docker/nginx/html:/usr/share/nginx/html \
 -v /opt/docker/nginx/logs:/var/log/nginx \
 -v /opt/docker/nginx/conf/:/etc/nginx \
 -d nginx:1.10
 
 docker run -p 80:80 -p 443:443 --name nginx443 \
 -v /usr/local/docker/nginx/html:/usr/share/nginx/html \
 -v /usr/local/docker/nginx/logs:/var/log/nginx \
 -v /usr/local/docker/nginx/conf/:/etc/nginx \
 -d nginx:1.20.1
2、部署MySQL
# 5.7版本
docker run -p 3306:3306 --name mysql57-app \
-v /app/mysql/log:/var/log/mysql \
-v /app/mysql/data:/var/lib/mysql \
-v /app/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:5.7

#8.x版本,引入了 secure-file-priv 机制,磁盘挂载将没有权限读写data数据,所以需要将权限透传,
或者chmod -R 777 /app/mysql/data

# --privileged 特权容器,容器内使用真正的root用户
docker run -p 3306:3306 --name mysql8-app \
-v /app/mysql/conf:/etc/mysql/conf.d \
-v /app/mysql/log:/var/log/mysql \
-v /app/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--privileged \ 
-d mysql

docker run -d --name mysql \-p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 \-v /usr/local/docker/mysql/mysql:/etc/mysql \-v /usr/local/docker/mysql/logs:/var/log/mysql \-v /usr/local/docker/mysql/data/:/var/lib/mysql \mysql:5.7 --lower_case_table_names=1
3、部署Redis
# 提前准备好redis.conf文件,创建好相应的文件夹。如:
port 6379
appendonly yes
#更多配置参照 https://raw.githubusercontent.com/redis/redis/6.0/redis.conf
docker run -p 6379:6379 --name redis \
-v /app/redis/redis.conf:/etc/redis/redis.conf \
-v /app/redis/data:/data \
-d redis:6.0.8 \
redis-server /etc/redis/redis.conf --appendonly yes
4、部署ElasticSearch
#准备文件和文件夹,并chmod -R 777 xxx
#配置文件内容,参照
https://www.elastic.co/guide/en/elasticsearch/reference/7.5/node.name.html 搜索相
关配置
# 考虑为什么挂载使用esconfig ...
docker run --name=elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
-v /app/es/data:/usr/share/elasticsearch/data \
-v /app/es/plugins:/usr/shrae/elasticsearch/plugins \
-v esconfig:/usr/share/elasticsearch/config \
-d elasticsearch:7.12.0

#######################################

docker pull elasticsearch:7.4.2  存储和检索数据
docker pull kibana:7.4.2 可视化检索数据    

mkdir -p /opt/docker/elasticsearch/config # 用来存放配置文件
mkdir -p /opt/docker/elasticsearch/data  # 数据
echo "http.host: 0.0.0.0" >/opt/docker/elasticsearch/config/elasticsearch.yml # 允许任何机器访问
chmod -R 777 /opt/docker/elasticsearch/ ## 设置elasticsearch文件可读写权限

# 启动es
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e  "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /opt/docker/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /opt/docker/elasticsearch/data:/usr/share/elasticsearch/data \
-v  /opt/docker/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2

#以后再外面装好插件重启就可

#特别注意:
-e ES_JAVA_OPTS="-Xms64m -Xmx128m" \ 测试环境下,设置 ES 的初始内存和最大内存,否则导致过大启动不了ES

# 开机启动
docker update elasticsearch --restart=always

# 启动kibana
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://42.192.52.168:9200 -p 5601:5601 -d kibana:7.4.2

http://42.192.52.168:9200 改成自己Elasticsearch上的地址
5、部署Tomcat
# 考虑,如果我们每次 -v 都是指定磁盘路径,是不是很麻烦?
docker run --name tomcat-app -p 8080:8080 \
-v tomcatconf:/usr/local/tomcat/conf \
-v tomcatwebapp:/usr/local/tomcat/webapps \
-d tomcat:jdk8-openjdk-slim-buster
6、部署dubbo-admin
docker run -d \
--name dubbo_admin \
-p 8083:8080 \
-e dubbo.registry.address=zookeeper://172.16.253.50:2181 \
-e dubbo.admin.root.password=root \
-e dubbo.admin.guest.password=root \
chenchuxin/dubbo-admin 
7、部署activemq
docker run --name='activemq' \
  -itd \
  -p 8161:8161 \
  -p 61616:61616 \
  -e ACTIVEMQ_ADMIN_LOGIN=admin \
  -e ACTIVEMQ_ADMIN_PASSWORD=admin \
  --restart=always \
  -v activemq_data:/data/activemq \
  -v activemq_log:/var/log/activemq \
  -v activemq_conf:/opt/activemq/conf \
  webcenter/activemq:latest
8、YAPI
# 启动 MongoDB
docker run -d --name mongo-yapi mongo

# 获取yapi镜像
docker pull registry.cn-hangzhou.aliyuncs.com/anoy/yapi

# 初始化数据库索引及管理员账号
docker run -it --rm \
  --link mongo-yapi:mongo \
  --entrypoint npm \
  --workdir /api/vendors \
  registry.cn-hangzhou.aliyuncs.com/anoy/yapi \
  run install-server
  
# 启动yapi服务
docker run -d \
  --name yapi \
  --link mongo-yapi:mongo \
  --workdir /api/vendors \
  -p 3000:3000 \
  registry.cn-hangzhou.aliyuncs.com/anoy/yapi \
  server/app.js
9、重启策略
no,默认策略,在容器退出时不重启容器
on-failure,在容器非正常退出时(退出状态非0),才会重启容器
on-failure:3,在容器非正常退出时重启容器,最多重启3次
always,在容器退出时总是重启容器
unless-stopped,在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容
器
10、RabbitMQ
docker search rabbitmq

docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq

docker exec -it 镜像ID /bin/bash
# 开启Web-UI后台界面
rabbitmq-plugins enable rabbitmq_management

http://linuxip地址:15672,用户名和密码默认都是guest

# stats in management UI are disabled on this node
docker exec -it {rabbitmq容器名称或者id} /bin/bash
cd /etc/rabbitmq/conf.d/
echo management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf
# 重启容器

2、docker exec

# 进入容器
docker exec -it 容器名或者容器id /bin/bash

# 0用户,以特权方式进入容器
docker exec -it -u 0:0 --privileged myredis /bin/bash

3、docker build

docker build -t imageName -f DockerfileName . 

# 不带缓存构建
docker build --no-cache

3、容器的状态

Created(新建)、Up(运行中)、Pause(暂停)、Exited(退出)

三、网络和存储原理

问题:

  • 容器: 某个软件完整的运行环境;包含了一个小型的linux系统

  • 宿主机里面同时4个nginx; 一个nginx运行时完整环境有20MB?

    • 4个nginx 合起来占用多少的磁盘空间
    • 80?如果每一个容器启动都是一个完整的linux系统一定会很大…

docker装的和宿主机的优缺点:

优点:docker的移植性、便捷性高于在宿主机部署、进程隔离、很方便的资源限制

缺点:docker基于虚拟化技术,损失不到3%的性能。

镜像 容器

镜像(Image):固定不变的。一个镜像可以启动很多容器

容器(Container):文件系统可能logs经常变化的,一个镜像可以启动很多容器。

docker在底层使用自己的存储驱动。来组件文件内容 storage drivers。

1、Docker存储

1、镜像如何存储

截取的nginx的分层

docker history nyginx

nginx这个镜像怎么存的
使用:docker image inspect nginx

指示了镜像怎么存的

LowerDir :底层目录; diff(只是存储不同);包含小型linux和装好的软件

/var/lib/docker/overlay2/67b3802c6bdb5bcdbcccbbe7aed20faa7227d584ab37668a03ff6952e
631f7f2/diff:用户文件;

/var/lib/docker/overlay2/f56920fac9c356227079df41c8f4b056118c210bf4c50bd9bb077bdb4
c7524b4/diff: nginx的启动命令放在这里

/var/lib/docker/overlay2/0e569a134838b8c2040339c4fdb1f3868a7118dd7f4907b40468f5fe6
0f055e5/diff: nginx的配置文件在这里

/var/lib/docker/overlay2/2b51c82933078e19d78b74c248dec38164b90d80c1b42f0fdb1424953
207166e/diff: 小linux系统
  • 倒着看

    • 小linux系统(FROM apline) + Dockerfile的每一个命令可能都引起了系统的修改,所以和git一样,只记录变化

      ls -i
      

    • 我们进入到这个镜像启动的容器,容器的文件系统就是镜像的;
    • docker ps -s;可以看到这个容器真正用到的文件大小
    • 容器会自己建立层;如果想要改东西,把改的内容复制到容器层即可 docker inspect container
"LowerDir":
"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462
c862f1e9a0562de2384dbc-
init/diff:/var/lib/docker/overlay2/e3b8bdbb0cfbe5450696c470994b3f99e
8a7942078e2639a788027529c6278f7/diff:/var/lib/docker/overlay2/67b380
2c6bdb5bcdbcccbbe7aed20faa7227d584ab37668a03ff6952e631f7f2/diff:/var
/lib/docker/overlay2/f56920fac9c356227079df41c8f4b056118c210bf4c50bd
9bb077bdb4c7524b4/diff:/var/lib/docker/overlay2/0e569a134838b8c20403
39c4fdb1f3868a7118dd7f4907b40468f5fe60f055e5/diff:/var/lib/docker/ov
erlay2/2b51c82933078e19d78b74c248dec38164b90d80c1b42f0fdb14249532071
66e/diff",
       "MergedDir":
"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462
c862f1e9a0562de2384dbc/merged",
       "UpperDir": (镜像的上层可以感知变
化)"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d
462c862f1e9a0562de2384dbc/diff",【容器的修改后的文件,保存再宿主机哪里呀。
容器删除后,那些容器目录还存在吗?一定不再】
       "WorkDir":
"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462
c862f1e9a0562de2384dbc/work"
  • MergedDir :合并目录;容器最终的完整工作目录全内容都在合并层;数据卷在容器层产生;所有的增删改都在容器层;

  • UpperDir :上层目录;
  • WorkDir :工作目录(临时层),pid;

LowerDir(底层)\UpperDir()\MergedDir\WorkDir(临时东西)

docker底层的 storage driver完成了以上的目录组织结果;

哪些东西适合容器运行?

  • docker启动一个MySQL,默认什么都不做?

  • MySQL就会丢失数据

    • 文件挂载
    • docker commit:能提交,MySQL的容器,也能提交。100G;100G,一般不采用这种方式
1、Images and layers

Docker映像由一系列层组成。 每层代表图像的Dockerfile中的一条指令。 除最后一层外的每一层都是只读的。 如以下Dockerfile:

  • Dockerfile文件里面几句话,镜像就有几层
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
# 每一个指令都可能会引起镜像改变,这些改变类似git的方式逐层叠加。

该Dockerfile包含四个命令,每个命令创建一个层。

FROM语句从ubuntu:15.04映像创建一个图层开始。

COPY命令从Docker客户端的当前目录添加一些文件。

RUN命令使用make命令构建您的应用程序。

最后,最后一层指定要在容器中运行的命令。

每一层只是与上一层不同的一组。 这些层彼此堆叠。

创建新容器时,可以在基础层之上添加一个新的可写层。 该层通常称为“容器层”。 对运行中

的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此薄可写容

器层。

2、Container and layers
  • 容器和镜像之间的主要区别是可写顶层。

  • 在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。

  • 删除容器后,可写层也会被删除。 基础图像保持不变。 因为每个容器都有其自己的可写容

​ 器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对同一基础映像的访问,

​ 但具有自己的数据状态。

  • 下图显示了共享同一Ubuntu 15.04映像的多个容器。

在这里插入图片描述

3、磁盘容量预估

docker ps -s

size:用于每个容器的可写层的数据量(在磁盘上)。

virtual size:容器使用的用于只读图像数据的数据量加上容器的可写图层大小。

多个容器可以共享部分或全部只读图像数据。

从同一图像开始的两个容器共享100%的只读数据,而具有不同图像的两个容器(具有相同的层)共享这些公共

层。 因此,不能只对虚拟大小进行总计。这高估了总磁盘使用量,可能是一笔不小的数目。

4、镜像如何挑选

busybox:是一个集成了一百多个最常用Linux命令和工具的软件。linux工具里的瑞士军刀

alpine:Alpine操作系统是一个面向安全的轻型Linux发行版经典最小镜像,基于busybox,功能比

Busybox完善。

slim:docker hub中有些镜像有slim标识,都是瘦身了的镜像。也要优先选择

无论是制作镜像还是下载镜像,优先选择alpine类型.

5、Copy On Write
  • 写时复制是一种共享和复制文件的策略,可最大程度地提高效率。
  • 如果文件或目录位于映像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使用现有文件。
  • 另一层第一次需要修改文件时(在构建映像或运行容器时),将文件复制到该层并进行修改。 这样可以将I / O和每个后续层的大小最小化。

2、容器如何挂载

每一个容器里面的内容,支持三种挂载方式:

1)、docker自动在外部创建文件夹自动挂载容器内部指定的文件夹内容【Dockerfile VOLUME指令的作用】

2)、自己在外部创建文件夹,手动挂载

3)、可以把数据挂载到内存中。

–mount 挂载到 linux宿主机,手动挂载(不用了)

-v 可以自动挂载,到linux主机或者docker自动管理的这一部分区域

  • Volumes(卷) :存储在主机文件系统的一部分中,该文件系统由Docker管理(在Linux上是“ / var /lib / docker / volumes /”)。 非Docker进程不应修改文件系统的这一部分。 卷是在Docker中持久存储数据的最佳方法。
  • Bind mounts(绑定挂载) 可以在任何地方 存储在主机系统上。 它们甚至可能是重要的系统文件或目录。 Docker主机或Docker容器上的非Docker进程可以随时对其进行修改。
  • tmpfs mounts(临时挂载) 仅存储在主机系统的内存中,并且永远不会写入主机系统的文件系统
1、volume(卷)
  • 匿名卷使用
docker run -dP -v :/etc/nginx nginx
#docker将创建出匿名卷,并保存容器/etc/nginx下面的内容
# -v 宿主机:容器里的目录 
  • 具名卷使用
docker run -dP -v nginx:/etc/nginx nginx
#docker将创建出名为nginx的卷,并保存容器/etc/nginx下面的内容

如果将空卷装入存在文件或目录的容器中的目录中,则容器中的内容(复制)到该卷中。

如果启动一个容器并指定一个尚不存在的卷,则会创建一个空卷。

-v 宿主机绝对路径:Docker容器内部绝对路径:叫挂载;这个有空挂载问题

-v 不以/开头的路径:Docker容器内部绝对路径:叫绑定(docker会自动管理,docker不会把他当成目录,而把它当前卷)

以上用哪个比较好??????

  • 如果自己开发测试,用 -v 绝对路径的方式
  • 如果是生产环境建议用卷
  • 除非特殊 /bin/docker 需要挂载主机路径的则操作 绝对路径挂载
nginx--Docker
/usr/share/nginx/html

nginx测试html挂载几种不同情况:

不挂载 效果:访问默认欢迎页
-v /root/html:/usr/share/nginx/html 效果:访问forbidden
-v html:/usr/share/nginx/html:ro 效果:访问默认欢迎页(:ro 表示只读)
-v /usr/share/nginx/html 效果:匿名卷 (什么都不写也不要加冒号,直接写容器内的目录)

原因:
-v html:/usr/share/nginx/html; docker inspect 容器的时候; docker自动管理的方式
# -v不以绝对路径方式;
### 1、先在docker底层创建一个你指定名字的卷(具名卷) html
### 2、把这个卷和容器内部目录绑定
### 3、容器启动以后,目录里面的内容就在卷里面存着;
#####-v nginxhtml:/usr/share/nginx/html 也可以以下操作
## 1、 docker create volume nginxhtml 如果给卷里面就行修改,容器内部的也就改
了。
## 2、 docker volume inspect nginxhtml
## 3、docker run -d -P -v nginxhtml:/usr/share/nginx/html --
name=nginx777 nginx
# 可以看到
"Mounts": [
     {
        "Type": "volume", //这是个卷
        "Name": "html",  //名字是html
        "Source": "/var/lib/docker/volumes/html/_data",  //宿主
机的目录。容器里面的哪两个文件都在
        "Destination": "/usr/share/nginx/html",  //容器内部
        "Driver": "local",
        "Mode": "z",
        "RW": true,  //读写模式
        "Propagation": ""
     }
   ]
#卷:就是为了保存数据
docker volume  #可以对docker自己管理的卷目录进行操作;
/var/lib/docker/volumes(卷的根目录)
2、bind mount

如果将绑定安装或非空卷安装到存在某些文件或目录的容器中的目录中,则这些文件或目录会被

安装遮盖,就像您将文件保存到Linux主机上的/ mnt中一样,然后 将USB驱动器安装到/ mnt中。

在卸载USB驱动器之前,/ mnt的内容将被USB驱动器的内容遮盖。 被遮盖的文件不会被删除或更

改,但是在安装绑定安装或卷时将无法访问。

总结:外部目录覆盖内部容器目录内容,但不是修改。所以谨慎,外部空文件夹挂载方式也会导

致容器内部是空文件夹

docker run -dP -v /my/nginx:/etc/nginx nginx

# bind mount和 volumes 的方式写法区别在于 
# 所有以/开始的都认为是 bind mount ,不以/开始的都认为是 volumes.

警惕bind mount 方式,文件挂载没有在外部准备好内容而导致的容器启动失败问题

# 一行命令启动nginx,并且配置文件和html页面。需要知道卷的位置才能改 
docker run -d -P -v nginxconf:/etc/nginx/ -v nginxpage:/usr/share/nginx/html nginx 
# 想要实现 docker run -d -P -v /root/nginxconf:/etc/nginx/ -v /root/nginxhtml:/usr/share/nginx/html --name=nginx999 nginx 
### 1、提前准备好东西 目录nginxconf,目录里面的配置we年都放里面,,再调用命令 
### 2、docker cp nginxdemo:/etc/nginx /root/nginxconf #注意/的使用 
### 3、docker run -d -P -v /root/nginxconf:/etc/nginx/ -v /root/nginxhtml:/usr/share/nginx/html --name=nginx999 nginx

3、管理卷

docker volume create xxx:创建卷名
docker volume inspect xxx:查询卷详情
docker volume ls: 列出所有卷
docker volume prune: 移除无用卷

4、docker cp

cp的细节

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- :把容器里面的复制出来
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH:把外部的复制进去
  • SRC_PATH 指定为一个文件

    • DEST_PATH 不存在:文件名为 DEST_PATH ,内容为SRC的内容
    • DEST_PATH 不存在并且以 / 结尾:报错
    • DEST_PATH 存在并且是文件:目标文件内容被替换为SRC_PATH的文件内容。
    • DEST_PATH 存在并且是目录:文件复制到目录内,文件名为SRC_PATH指定的名字
  • SRC_PATH 指定为一个目录

    • DEST_PATH 不存在: DEST_PATH 创建文件夹,复制源文件夹内的所有内容
    • DEST_PATH 存在是文件:报错
    • DEST_PATH 存在是目录
      • SRC_PATH 不以 /. 结束:源文件夹复制到目标里面
      • SRC_PATH 以 /. 结束:源文件夹里面的内容复制到目标里面

自动创建文件夹不会做递归。把父文件夹做好

docker cp index.html mynginx4:/usr/share/nginx/html
docker cp mynginx4:/etc/nginx/nginx.conf nginx.conf

2、Docker网络

1、端口映射

docker create -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name hello-mysql
mysql:5.7

2、容器互联

–link name:alias ,name连接容器的名称,alias连接的别名

场景:我们无需暴露mysql的情况下,让web应用使用mysql;

docker run -d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d --link mysql01:mysql --name tomcat tomcat:7
docker exec -it tomcat bash
cat /etc/hosts
ping mysql

3、自定义网络

1、默认网络原理

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

Linux虚拟网络技术。

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让

他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进

行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器

系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

原理:

1、每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。桥接网卡

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

3、docker run -d -P --name tomcat --net bridge tomcat:8

2、网络模式
网络模式配置说明
bridge模式–net=bridge默认值,在Docker网桥docker0上为容器创建新的网络栈
none模式–net=none不配置网络,用户可以稍后进入容器,自行配置
container模式–net=container:name/id容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace。
host模式–net=host容器和宿主机共享Network namespace
用户自定义–net=自定义网络用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络
3、自建网络测试
#1、docker0网络的特点。,
默认、域名访问不通、--link 域名通了,但是删了又不行
#2、可以让容器创建的时候使用自定义网络
1、自定义创建的默认default "bridge"
2、自定义创建一个网络网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
docker run -d -P --name=tomcat1 --network=mynet tomcat:jre8-alpine
docker run -d -P --name=redisserver --network=mynet redis
# 以上tomcat和redis可以互相ping通
# 对于没有ping命令的容器可以这样测试
docker run -it --network container:redisserver alpine
# 所有东西实时维护好,直接域名ping通
docker network connect [OPTIONS] NETWORK CONTAINER
#3、跨网络连接别人就用。把tomcat加入到mynet网络
docker network connect mynet tomcat
效果:
1、自定义网络,默认都可以用主机名访问通
2、跨网络连接别人就用 docker network connect mynet tomcat
#4、命令
1、容器启动,指定容器ip。 docker run --ip 192.168.0.3 --net 自定义网络 
2、创建子网。docker network create --subnet 指定子网范围  --driver bridge 所有东西实时
维护好,直接域名ping同
3、docker compose 中的网络默认就是自定义网络方式

更多内容:

更多内容大家可以关注一下个人博客网,https://blog.xueqimiao.com/,内容更丰富喔。
在这里插入图片描述
回复Docker可以获取完整md文档喔,谢谢关注。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小薛博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值