Docker学习笔记(详细)
2024-09-08 00:07:49
目录
01 介绍
- 为什么会有docker:开发与运维之间的矛盾,不仅打包代码,环境也一并打包
- 为什么用docker:基于容器的虚拟化,仅包含业务运行所需要的runtime环境
- 更高效:无操作系统虚拟化开销
- 计算:轻量,无额外开销
- 存储:系统盘aufs/dm/overlayfs;数据盘volume
- 网络:宿主机网络,NS隔离
- 更敏捷、更灵活
- 分层的存储和包管理、devops理念
- 支持多种网络配置
- 更高效:无操作系统虚拟化开销
- docker理念:一次封装,到处运行,解决运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的虚拟化技术,基于Go语言,C/S架构
- 基本组成:镜像、容器、仓库
- 官网:https://www.docker.com/
02 Docker安装
参考:https://blog.csdn.net/weixin_37680513/article/details/116858377
03 Docker常用命令
帮助命令
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker --help # 帮助命令
# https://docs.docker.com/reference/
- 镜像命令
docker images [options] [name] 列出本地镜像
-a 列出所有镜像
-q 列出id, 可以组合使用-qa
--digests 显示摘要
--no-trunc 不截取id,显示完整id
docker search imageName [options] 搜索镜像,从hub.docker.com
-s xx 显示star xx以上的镜像,xx是数字
--no-trunc 显示完整description
--automated 只列出automated的镜像
docker pull imageName[:TAG] 拉取镜像,默认[:latest]
docker rmi [options] imageName[:TAG] 删除镜像,默认[:latest],可删多个
-f 强制删除
docker rmi -f $(docker images -qa) 删除所有镜像
- 容器命令
docker run [options] imageName [command][args] 新建并启动容器
--name="newName" 为容器指定一个名称
--name newName
--volumes-from id/name 从容器继承容器卷
-d 后台运行容器,并返回容器id,也即启动守护式容器,docker容器后台运行必须有一个前台进程,否则立即自杀,如果不是那些一直挂起的命令,比如top tail 就会自动退出的
-i 以交互模式运行容器,通常与-t同时使用
-t 为容器重新分配一个伪终端,通常与-i同时使用
-P 随机端口映射
-p 指定端口映射,有以下4种形式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
docker ps [options] 列出当前正在运行的容器
-a 显示当前及历史上运行过的
-l 显示最近创建的容器
-n num 显示最近创建的num个容器
-q 静默模式,只显示容器编号,-lq,只返回最近创建的容器编号
--no-trunc 不截断输出
exit 退出并停止容器
ctrl + P + Q 只退出容器,不停止
docker start id/name 启动容器
docker restart id/name 重启容器
docker stop id/name 停止容器
docker kill id/name 强制停止容器
docker rm id/name 删除已经停止的容器,-f强制删除,不管是否正在运行
docker rm -f $(docker ps -qa) 一次删除所有容器
docker ps -qa | xargs docker rm -f 一次删除所有容器
docker logs id/name 打印容器日志
-t 加上时间
-f 跟随打印
--tail n 只打印最后n行
docker top id/name 列出容器的进程
docker inspect id/name 查看容器内部细节,返回json字符串
docker attach id/name 直接进入容器,启动命令的终端,不会启动新的进程
docker exec -it id/name command 在外部执行容器内部的命令,打开新的命令终端,可以启动新的进程
docker cp id/name:path hostpath 从容器拷贝数据到宿主机
04 Docker镜像
- 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和开发的软件,它包含运行某个软件所需要的所有内容,包括代码、运行时、库、环境变量和配置文件
- UnionFS(联合文件系统):是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时将不同目录挂载到同一个虚拟文件系统下,unionfs是docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像,可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,最终的文件系统会包含所有底层的文件和目录。
- docker镜像加载原理:docker镜像实际上是由一层一层的文件系统组成(UnionFS),
- bootfs:主要包含bootloader和kernel,bootloader主要引导加载kernel,linux刚启动时加载bootfs,在docker镜像的最底层是bootfs,这一曾与典型了linux系统一样,包含boot加载器和内核,boot加载完之后真个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统会卸载bootfs
- rootfs:在bootfs之上,包含的是典型linux系统的中的/dev等标准目录和文件,rootfs就是各种不同的操作系统的发行版,比如ubuntu。对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序就可以了,底层直接用主机的内核,自己只提供rootfs,因此,不同发行版可以公用bootfs
- 为什么要采用这种分层结构:共享资源,如果多个镜像都从相同的bas镜像构建,那么宿主机只需提供磁盘上的一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以共享
- 特点:docker镜像都是只读的;当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称为容器层,容器之下的都叫镜像层
- 提交容器副本使之成为一个新的镜像:
docker commit -a="author" -m="description of this version image" id/name newName[:TAG]
05 Docker容器数据卷
- 是什么:使用卷来保存docker中的数据,如果没有commit生成新的镜像,作为新的镜像的一部分,当容器删除后,数据自然也就没有了
- 作用:容器的持久化、容器间继承和共享数据
- 添加数据卷:
-- 直接命令添加
docker run -it -v /宿主机目录:/容器内目录[:ro] id/name
# ro表示read only容器内只能读宿主机目录内文件,不可修改
-- DockerFile添加
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
- 构建
docker build -f /dockerFile -t imageName . # .表示在当前目录创建,不写-f默认读取Dockerfile
- 运行这个镜像会在容器中添加相应的卷,使用docker inspect id/name查看,在宿主机中会有默认的对应目录:/var/lib/docker/volumes/id/_data/
- 如果遇到docker访问出现cannot open directory .:Permission denied
解决办法:在挂载目录后多加一个 --privileged=true
- 数据卷容器:创建的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器称为数据卷容器。
docker run -it --name dc2 --volumes-from dc1
- 那么dc2里就有dc1的数据卷,dc1的数据卷是与宿主机共享的
- 数据卷的生命周期一直持续到没有容器使用它为止
问题:使用docker run -it -v /xx:/xxx id 创建数据卷之后,容器停止,再开启数据还有吗?容器删除再开还有吗?应该是有的
06 Dockerfile解析
- dockerfile是用来构建docker镜像的构建文件,是由一系列命令和参数构成的脚本
- 编写、构建(docker build)、运行(docker run)
Dockerfile构建过程解析
- Dockerfile是软件原材料、镜像是交付品、容器则是软件的运行态。dockerfile面向开发,docker镜像成为i交付标准,docker容器则涉及部署与运维,三者缺一不可,合力充当docker体系的基石
- Dockerfile:需要定义一个dockerfile,定义了进程需要的一切东西,包括执行代码、文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程等等(当应用进程与系统服务和内核进程打交道时,需要考虑如何设计namespace的权限控制)
- docker镜像:dockerfile定义一个文件后,docker build会产生一个docker镜像,当运行镜像时,开始提供服务
- docker容器:容器时直接提供服务的
-- Dockerfile基础知识
- 每条保留字指令都必须大写,后面都要跟至少一个参数
- 指令从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
-- docker执行dockerfile的大致流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器做出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行dockerfile中的下一条指令直到所有的指令都执行完成
Dockerfile体系结构
FROM 基础镜像,当前镜像基于哪个镜像
MAINTAINER 镜像维护者的姓名和邮箱
RUN 容器构建时需要运行的命令
EXPOSE 当前容器对外暴露的端口
WORKDIR 指定在创建容器后,终端默认登陆进来的工作目录,默认/
ENV 用来在构建环境变量中设计环境变量
ADD 将宿主机目录下的文件拷贝进镜像,且ADD会解压tar包、自动处理url
COPY 类似ADD,但是不解析,只是拷贝,COPY src dest、COPY["src","dest"]
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定一个容器启动时要运行的命令,可以有多个,但只有最后一个生效,CMD会被docker run之后的命令覆盖
ENTRYPOINT 与CMD一样,但是不会被覆盖,docker run后的命令追加到ENTRYPOINT里面
ONBUILD 当构建一个被继承的dockerfile命令时,父镜像在被继承后父镜像的ONBUILD被触发
# EXPOSE只是展示性的,为了方便不同开发人员维护!!不用EXPOSE也可以使用-p命令指定端口,但是如果使用了,在使用-P命令时可以随机映射到主机的端口,因为是随机的,所以也没什么用
案例
base镜像:scratch, 参考hub.docker.com
07 Docker常用安装
搜索镜像 docker search name
拉取镜像 docker pull name
查看镜像 docker images [name]
启动镜像 docker run -it -p hostPort:CotainterPort id/name
停止容器 docker stop id/name
移除容器 docker rm id/name
-- tomcat
docker search tomcat
docker pull tomcat
docker images
docker run -it -p 8080:8080 tomcat
-- mysql
docker search mysql:5.6
docker pull mysql:5.6
docker run -p 3306:3306 --name mysql \
-v /xxx/mysql/conf:/etc/mysql/conf.d
-v /xxx/mysql/logs:/logs
-v /xxx/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=999999
-d mysql:5.6
docker exec -it id/name /bin/bash
mysql -uroot -p999999
-- redis
docker pull redis:3.2
docker run -p 6379:6379 \
-v /xxx/data:/data \
-v /xxx/conf:/usr/local/etc/redis/redis.conf \
-d redis:3.2 redos-server /usr/local/etc/redis/redis.conf \
--appendonly yes
docker exec -it id/name redic-cli # 连接客户端
08 本地镜像发布到阿里云
1 - 生成镜像
docker build -f Dockerfile -t name .
docker commit -a xxx -m xxx id/name:xxx
2 - 在dev.aliyun.com创建仓库、命名空间
3 - 推送
docker login --username=registry.cn-hangzhou.aliyuncs.com
docker tag id registry.cn-hangzhou.aliyuncs.com/xxx/xxx:xxx
docker push registry.cn-hangzhou.aliyuncs.com/xxx/xxx:xxx
4 - 使用:在dev.aliyun.com上搜索,复制地址docker pull
docker pull registry.cn-hangzhou.aliyuncs.com/xxx/xxx:xxx
可视化
- portainer:docker图形化界面管理工具,提供一个后台面板供我们操作
- rancher
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Docker 网络
理解docker0
# 查看ip地址
ip addr # address, a都可以
ifconfig
# 原理:
# 1、每启动一个容器,docker就会给容器分配一个ip,只要安装了docker,就会有一个docker0网卡。桥接模式,使用veth-pair技术
# 2、每启动一个容器,就多了一对网络,veth-pair就是一对的虚拟设备接口,它们都是成对出现的,一端连接协议,一端彼此相连。正因为有这个特性,veth-path充当一个桥梁,连接各种虚拟网络设备
# 容器和容器直接是可以互相ping通的
# 所有容器默认共用一个路由器docker0(网关),所有容器在不指定网络的情况下,都是docker0路由的,docker会给容器分配一个默认的可用ip
--link
- --link后加容器名,可用直接通过容器名访问,是在hosts文件里添加了映射
自定义网络
# 查看所有的docker网络
docker network --help
# 网络模式
# bridge # 桥接模式,桥接docker(默认)
# none # 不配置网络
# host # 和宿主机共享网络
# container # 容器网络连通(用的少,局限性很大)
# 默认 --net bridge
# 创建自己的网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
docker network inspect mynet # 查看自己创建的mynet
docker run -d -P --name tomcat-net-01 --net mynet tomcat # 使用自己创建的网络而不是docker0,不使用--link可以使用ping名字ping通
# 结论:自定义docker网络帮我们维护好了ip和名字的对应关系,推荐这样使用网络。不同集群使用不同的网络,保证集群健康
网络连通
docker0网络下的(默认)容器如何连接自定义网络下的容器?通过创建网络连接使容器有两个ip地址
docker network connect mynet <containerName> # 本质是将容器加入网络
docker network inspect mynet # 可以发现是直接加入的
最新文章
- 使用C#开发数据库应用系统
- Matlab中的persistent变量
- PowerShell并发控制-命令行参数之四问
- AppCan4.0:开发者要做有价值的APP
- android 官网处理图片 代码
- Windows 之间用rsync同步数据(cwRsyncServer配置)
- Ubuntu 12.04 安装Scrapy爬虫框架
- Tunnel Warfare
- structured sparsity model
- 使用JAVA进行MD5加密后所遇到的一些问题
- javascript中的throttle和debounce
- NoSql的产生
- HDU 1260 Tickets(基础dp)
- 一次对象过大引起的gc性能问题的分析与定位
- ES创建mapping时字段别名
- log4j.properties配置与将异常输出到Log日志文件实例
- Android布局:宽度适应的横向跟随,防止挤掉重要视图
- 【XSY2785】模型
- ElasticSearch6.1.1集群搭建
- Dagger2 导入项目