docker
-
docker的特性
- 轻量级的环境隔离
- 统一的封包和运行方式方式
-
docker hub 是docker的镜像仓库官网,里面可以方便的查找镜像和对应的tag
-
docker 是容器服务,里面运行的容器化的服务,容器里面装着我们的程序,它提供隔离的环境,提供统一的部署运行方式。
-
docker 在隔离的前提上是共享硬件资源的,VM一般是独占硬件资源的,新版本的linux虚拟机一般也是资源共享的,window的虚拟机还是资源独占的。
-
容器,镜像,仓库,容器服务之间的关系
- 镜像:按照一定规范打成的程序包。
- 镜像仓库:存放镜像的地方
- 容器:提供给镜像运行实例的隔离环境。容器里面跑着的是镜像的实例程序。
- 容器服务:提供容器这种服务的程序,docker就是容器化服务实现软件。
-
docker,是linux容器化服务的实现, 需要linux的内核环境,window版本是在window上虚拟化了一个linux环境,然后在上面跑的docker。
-
构造镜像
- docker build -t 镜像名字:tag (这时候需要当前目录有DockerFile存在)
- DockerFile是告诉docker 应该怎么去生成一个镜像。
-
创建并且运行一个docker 容器: docker run --name 容器名字 镜像名字
-
docker 镜像是存在 /var/lib/docker 下面
-
docker 是一个 CS架构,可以通过远程客户端连接远程docker服务。
-
阿里云提供了容器镜像服务,并且个人版是免费的,可以支持保存我们自己的镜像。
如果有上传需求
然后写入加速库
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://x2k31e1o.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
-
docker 常见命令
-
docker info 查看docker 信息
-
systemctl start/stop/restart/status/enable/disable docker docker服务的启动/关闭/重启/状态/开机启动/关闭开机启动
-
docker exec -it 容器id bash 进入容器内部,相当于齐了一个新的终端(一般用这个)
-
docker attach 容器Id 进入交互式命名,相当于重新连上启动的时候的那个终端
-
docker run xxx 加载镜像+创建容器+启动容器
- docker run -d xxx 后台启动
-
docker ps 查看 docker 容器进程
-
docker top 容器ID 查看 docker容器进程前面几个
-
docker stats 查看容器资源统计
-
docker images 查看镜像
-
docker rm 容器Id 删除 容器
- docker ps -aq | xargs docker rm -f 强制删除所有容器
-
docker rmi 镜像id 删除镜像
-
docker start/stop/restart镜像Id 开始/关闭/重启一个容器
-
docker inspect 容器ID 查看指定容器的详情
-
docker rename 容器ID 重命名
-
docker logs 容器ID 查询日志
-
docker search 容器名字 --limit 10 查询容器(直接切docker hub 查询更加方便,一般用有official标记的
-
docker system df 查看容器镜像数据卷磁盘占用情况
-
docker cp 原文件 目标文件 宿主机和容器之间文件复制
- 容器id:文件路径 容器内文件表示方式
-
docker export 容器Id > 文件 把当前容器打包成一个文件备份
- docker export 36244ed84aa5 > ubuntu.tar
-
cat 镜像文件.tar | docker import - 用户名/仓库名/tag 把镜像文件恢复成一个镜像(执行以后会多了一个指定名字的镜像)。这个镜像的内容和之前容器一样。
-
docker commit -m "备注" -a "作者备注" 容器Id 账号/仓库/tag 使用已经有的容器生成一个镜像
- 这个容器比镜像多了一层,并且这上面多的那一层上面的修改被保存到新镜像中,后面同新镜像创建的容器就已经有了上次修改过的东西
- 通过这样的方式我们甚至不用docker-compose就能包整个项目的所有模块都安装到一个Ubuntu上面去,然后把它做成一个镜像
-
使用远程仓库
- docker pull 仓库地址/命名空间/镜像名字:tagName 在指定仓库拉取镜像
- docker login --username=xxx 仓库地址 登录远程仓库
- docker tag 镜像id 仓库地址/命名空间/镜像名字:tagName 指定本地镜像关联那个远程镜像
- 这时候会生成另外一个REPOSITORY带有 仓库地址前缀的新镜像,后面我们推的也是这个
- docker push 仓库地址/命名空间/镜像名字:tagName 把本地镜像推送到指定仓库
- 如果不想docker hub 和 阿里云之类的仓库以外,我们还可以使用Docker Registry搭建自己的私有镜像仓库
-
docker build -t 新的镜像名字:tag . 按照当前目录的DockerFile构建镜像
-
-
docker run -it xxx bash
- exit 会退出会关闭容器
- ctrl+q+p 退出容器不会关闭容器
- 后面通过 docker exec -it 进去的 exit 不会退出
- 后面通过 docker attach 方式进去的,exit退出会关闭容器
-
docker run -d 的 程序必须有一个前台进程,不然会立即退出( nginx ubuntu 之类的 )
- docker run -d -it xxx 可以强制保留一个sh前台进程(-it默认会执行 /bin/bash)
-
docker的镜像是分成联合文件系统,这样做的好处是镜像模块可以复用,极大的减少存储和传输的数据量。
-
docker镜像的最底层是 bootfs ,第二次是rootfs,镜像都是只读的,容器层是可写的,新的容器启动的时候,一个新的可写层被加入到容器镜像顶部,这层可写的叫做容器层,下面不可写的部分都是镜像层。
-
docker Registry 是一个官方提供的 镜像仓库软件。我们可以使用它搭建私有镜像仓库
-
创建私有仓库
-
docker run -d -p 5000:5000 -v /opt/docker/registry:/tmp/registry --privileged=true registry
-
文件放在 /opt/docker/registry/
-
仓库地址就是 http://ip:5000
-
访问:http://192.168.100.150:5000/v2/_catalog 可以看到是空的
-
默认是不支持 http 协议的需要https,这时候可以修改 /etc/docker/daemon.json文件,让它认为这个地址是安全的
添加"insecure-registries":["ip:端口"],然后重启docker{ .......省略, "insecure-registries":["ip:端口"] }
systemctl daemon-reload
systemctl restart docker
-
-
DockerFIle 构建镜像
-
from 基于那个镜像
-
maintainet 维护人员信息
-
env 指定环境变量
- env 变量名字 变量值 指定变量
- $变量名字 引用变量
-
run 执行命名,有两种格式,执行时间点是构建镜像的时候
- run 命令 参数1 shell格式
- run ["命令,"参数1","参数2","参数3"] exec格式
-
cmd 执行命名,执行时间点是容器启动的时候
- dockerFIle可以有多个cmd 命令,但是只有最后一个生效
- cmd 命令会被 docker run [options] 镜像名字 cmd指令 ,后面的 cmd指令覆盖
-
entrypoint 运行命令,执行时间点是容器启动的时候
-
它和cmd 的区别在于 cmd 会被 docker run最后的命名覆盖,entrypoint 不会,并且在他后面使用cmd 来当做默认值,并且利用cmd 会被 docker run 后面参数覆盖来改变 参数。
-
entrypoint 也是只有最后一条会被执行
-
需要使用 exec格式entrypoint 才能和 cmd 一起用。shell 格式无效,cmd 不管写在 entrypoint前后都可以
entrypoint ["echo","2"] cmd ["3"]
-
-
expose 对外暴露端口
-
workdir 指定容器内的默认工作目录,终端登录进来就是这个目录 ,类似linux的 cd ~ 的位置
-
user 指定用哪个用户执行镜像内的操作
-
volume 指定容器卷
-
copy 复制宿主机的文件或者目录到 容器里第一地址是主机里面的文件,第二个是容器里面的文件
-
add 相当于 copy + 解压
- add xxx.tar.gz xxx.tar.gz 不会解压(复制到明确的文件不会)
- add xxx.tar.gz ./ 会解压(复制到目录会解压)
-
docker 网络
-
查看网络列表 docker network ls
-
删除没有用到的网路 docker network prune
-
删除指定网络 docker network rm 网络名字
-
docker的 网络模式
- bridge,产生一个子网络,子网络通过网桥和宿主机外面的网络通信,类似VMware网络模式 net模式
- docker run -d -p 8080:8080 --network bridge
- host模式,不产生子网络,容器直接使用主机的网卡,容器创建参数 -p无效,默认在主机占用同样的端口,冲突了以此+1后延。缺点很明显不能指定端口。
- docker run -d --network host
- none ,网卡都没有配置的网络模式,只有lo网卡
- docker run -d --network none
- container模式,和别的容器共享网卡host模式是和宿主机共享网卡,这是要考虑两个容器之间的端口冲突。如果指定的共享容器挂了,那么当前容器也就没有网络配置了,也就不能对外提供服务了。
- docker run -d -p 8081:8080 --network container:别的容器名字
- bridge,产生一个子网络,子网络通过网桥和宿主机外面的网络通信,类似VMware网络模式 net模式
-
指定容器网络 :docker run -d --network 网络名字 ,如果使用的 host 类型的网络 指定端口无效
-
默认不指定网络都是使用bridge这个网络
每个容器里面里面的网卡eth0都和网桥(docker0)相连,在外层主机创建vethxx的虚拟网卡和容器内的eth0对应
-
查看指定容器使用的网络:docker inspect 容器Id (最后面20行)
-
查看指定网络的 配置:docker network inspect 网络名字
-
自定义网络模式
- 创建网络:docker network create 网络名字
- 创建的网络都是 bridge 类型的
- 使用默认的网络(网络名是bridge的网络)的时候,容器之只能通过ip访问,不能通过容器名字访问
- 自定义网络可以通过容器名字访问
- 子网络里面的ip会伴随容器的销毁启动重新分配,容器之间通过子网ip访问是不可靠的,如果是通过宿主机IP访问是可以的。
docker volume
-
数据卷挂载中如果 提示 cannot open directory:Permission denied,那么需要在 挂载目录后面加上 --privileged=true
- 使用 --privileged=true 以后 容器里面的root 才是外面宿主机的 root ,否则只是普通用户。
- 这个 centos7 SELinux 的限制
- -v /a/b/c:/a/b/c --privileged=true
-
使用数据卷可以让容器和宿主机之间共享文件,也能让容器和容器之间共享文件。
-
可以同 docker inspect 容器Id 查看数据卷挂载情况,key为 mount 的键下面
-
-v /a/b/c:/a/b/c:ro 可以让容器内是只读(不写默认是rw)
-
-volumes-from 别的容器 和别的容器用同样的数据卷配置,这时候只是使用另一个容器的配置,另一个容器挂了也不影响
-
docker volume 和 -v 和 DockerFile 的vlolume的区别
docker compose
-
docker-compose管理的是一个的项目(project)下面的多个服务(service)之间的关系,单个dockerFile管理的是一个容器服务(或者说是一个组件),只使用docker 只能独立的管理 redis ,mysql ,java程序的运行和环境。compose可以编排他们之间的依赖关系,启动顺序。docker 和 docker-compose 分别管理着部分和整体。
-
在compose中内部ip默认是自动分配的, 可以使用service 名字作为访问这个容器的域名(IP),在spring配置文件或者别的需要访问redis,mysql地址的地方直接写入 对应对应容器的服务名字。
-
在 docker-compose.yml 里面配置容器服务之间的关系,然后使用 docker-compose up 就能一键启动整个项目
-
docker-compose build 构建镜像
- DockerFile 或者 jar包有变动都会重启 生成新的镜像 ,如果没有生成那么在后面 加上 --no-cahce=true
-
如果是重新生成镜像并且重启(脚本文件有变动或者jar内容有变动的时候)
- docker-compose down
- docker-compose build [--no-cache]
- docker-compose up -d
-
docker system prune 删除虚悬镜像(没有 tag 和 仓库名字的镜像),如果没有变更 tag名字就重新docker-compose build 老的镜像就会变成虚悬镜像
-
常见命令
- docker-compose up 创建并启动服务 类似 docker run 做了创建启动容器
- docker-compose up -d 创建并后台启动服务
- 如果默认文件不是DockerCompose.yml 那么可以通过 docker-compose -f xxx.yml up -d 来执行
- docker-compose start 启动服务
- docker-compose restart 重启服务
- docker-compose stop 关闭服务
- docker-compose down 关闭并移除服务
- docker-compose logs 查看日志
- docker-compose down --volumes 关闭并移除容器并删除容器清除存储
- docker-compose build --no-cache 重构服务,或者重新构建服务(会覆盖生成服务对应的镜像 )
- docker-compose -h 查看帮助
- docker-compose top 展示当前docker-compose编排过的容器进程
- docker-compose ps 查看当前compose进程
- docker-compose exec 容器Id /bin/bash/ 进入容器内部
- docker-compose config 配置检查
- docker-compose config -q 配置检查 有问题才输出
docker 可视化管理工具
-
portainer 是 docker轻量级的可视化管理工具
docker run -d -p 9000:9000 -p 8000:8000 --name portainer --restart=always --privileged=true -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
-
portainer 里面有很多app Templates 可以参考它知道 有哪些挂载点或者别的配置
-
docker stats 可以查看当前docker 个容器瞬时统计
-
docker system df 可以看磁盘状态
-
可以使用 CAdvisor+influxDB+grafana 来做 docker数据的采集+存储和展示,CIG 功能比 portainer功能强大,但是更加复杂
docker疑问和解决
- 容器内端口和宿主机端口如果冲突,那么后启动的程序就启动不了。
- 这时候可以不指定容器对外提供映射的端口
- CMD 和 run bash 区别
- run 的执行时间是在镜像生成的时候
- cmd 只能有一个,有多个的时候,前面的都无效,只有最后一个生效,并且是在创建容器的时候执行,cmd会被 docker 命令行参数替代。
- entrypoint 和 cmd 可以搭配使用,用cmd 作为后置传参
- 怎么在 docker bash 里面执行 ping 操作,和别的安装操作
- openjdk17的没有 ping,java1.8的有
- 可以自己安装apt-get install inetutils-ping 或者 microdnf install xxx (openjdk17 使用的microdnf)
- 实测microdnf连不上网
- 安装了 docker-compose 以后 docker 服务就不能stop了? 怎么才能停止?
- 感觉是一个bug,正常只要 通过 docker update restar=no 以后就应该可以停止
- 那些命令后面要加bash?
- docker exec -it 镜像Id后面 需要加bash 或者 /bin/bash
- docker run ....... 镜像名字 后面 如果是 ubuntu之类的镜像有些可以加bash ,别的不能乱加,否者会覆盖 cmd 里面的命令
- docker-compose volumes 和docker -v 区别
- 一样的,但是-v和 --mount有区别
- -v的全称是--volume
- -v的目录或自动创建 --mount 不会
- -v 和 --mount type=bind类似 ?
- -v 和 --mount的区别
- -v 宿主机绝对路径:容器绝对路径
- 如果 宿主机目录是null 就用容器的目录文件,如果宿主机目录文件不是null就用宿主机的文件
- --mount 有多重模式
- --mount type=volume,source=宿主机相对路径,destination=容器绝对路径
- 相对 宿主机/var/lib/docker/volumes/ 的路径
- 文件覆盖情况,如果source是空的就用destination的,如果source不是null的,就用source的
- 只能是映射目录
- --mount type=bind,source=宿主机相对路径,destination=容器绝对路径
- 文件覆盖情况,总是用source的覆盖,destination的内容
- 可以映射目录或者文件
- 大概只有强制映射宿主机目录到容器目录的时候考虑 --mount type=bind
- --mount type=tmpfs,source=宿主机相对路径,destination=容器绝对路径 ,文件只存在宿主机的内存中
- --mount type=volume,source=宿主机相对路径,destination=容器绝对路径
- -v 宿主机绝对路径:容器绝对路径
- shell格式 和 exec 格式区别
- shell 格式在 entrypoint 和 cmd 协同工作的时候无效
- 不指定 workdir 默认是哪里?
- 默认在/目录下
- add 和 copy 的区别
- add 目标地址是目录的时候会自动解压,目标地址是明确的文件的时候不会自动解压
- 多个cmd
- 只有最后一个生效
- 虚悬镜像 只要重复指定tag就会把老的镜像的tag挤掉,变成虚悬镜像
- 使用 docker system prune 删除