# docker概述(百度百科)
# 什么是docker
- 开源的应用容器引擎
# docker的组成
- dockerClient客户端
- Docker Daemon守护进程
- Docker Image镜像
- DockerContainer容器
# docker起源
- PaaS提供商dotCloud开源的基于LXC(Linux Container)的高级容器引擎,基于go语言进行开发
- Linux Container是一种轻量级内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。
- LXC当相遇c++中的NameSpace,将由单个操作系统管理的资源,划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。
- 自2013以来非常火热;
- LXC在Linux2.6的kernel就已经存在,由于其设计之初,并非为云计算考虑,因此其构建出的环境难以迁移和标准化管理。docker在这个问题上对其进行了实质性的革新,这也是docker最独特的地方。
一款开源软件能否在商业上成功,很大程度上依赖三件事-成功的userCase(用例),活跃的社区和一个好的故事.
# docker版本发布历史
- 2010年,dotCloud公司城里,提供一些paas的云计算服务,与LXC有关的容器技术
- 2013年,docker开源,没有引起行业的注意,dotCloud就会活不下去
- 2013年,发布0.0.1版本
- 2014年8月,Docker 1.0发布
- 2016年7月,Docker 1.8发布
- 2019年11月,Docker 1.25发布
- 2021年4月,Docker 1.29发布
- 2021年9月,Docker 2.0发布
- 2022年4月,Docker 2.5发布
# 架构
- 使用C/S架构管理Docker镜像
- Docker容器通过Docker镜像来创建(镜像与容器的关系类似于类与对象的关系)
- Docker daemon作为服务端接收来自客户的请求,并处理(创建、运行、分发容器);客户端和服务端既可以运行在一个机器上,也可以通过 socket或 Restful API来进行通信;
# docker适用场景
- 自动化部署
- 轻量级、私密的PAAS环境
- 实现自动化测试和持续集成/部署
- 部署与扩展webapp,数据库和后台服务
# docker命令(菜鸟教程)
# 容器生命周期命令
# run命令
- -i: 以交互模式运行容器,通常与 -t同时使用
- -t: 为日供气重新分配一个伪输入端口,通常与-i同时使用
docker run --name myng -d nginx:latest #后台模式启动nginx,并将容器命名为myng
docker run -p 80:80 -v /data:/data -d nginx:latest # 主机80端口映射到容器的80端口,主机的/data目录映射到容器的/data目录
# start/stop/restart命令
docker start myContainer #启动被停止的容器
docker stop myContainer # 停止运行中的容器
docker restart myContainer # 重启容器
# kill命令
docker kill myContainer #关闭运行中的容器
# pause/unpause
docker pause myContainer # 暂停容器中的所有进程
docker unpause myContainer # 恢复容器中的所有进程
# create命令
docker create --name myContainer nginx:lates #使用docker 镜像 nginx:latest创建一个容器,并命名为myContainer
# exec命令
docker exec -it mynginx /bin/sh /root/myShell.sh # 在myNginx容器中,以交互模式 执行容器内 /root/myShell.sh脚本
docker exec -it mynginx /bin/bash #在容器mynginx中,开启一个交互模式的终端
docker ps -a #可查看到已经在运行的容器
docker exec -it <容器id> /bin/bash #开启一个交互式终端
docker attach <容器id> #进入已有的交互式终端
# 容器操作命令
# exec命令
docker ps
#对正在执行的容器追加控制台命令
docker exec -it <容器ID或名称> /bin/sh
# ps命令
docker ps -a # 列出所有容器,包括未运行的
# top命令
docker top myContainer # 查看container容器中,运行的进程信息
# attach命令
docker attach myContainer #连接到正在运行的myContainer容器
# port命令
docker port myContainer #列出myContainer容器的端口映射情况
# rootfs命令(文件系统)
- 一个操作系统所包含的文件、配置和目录,并不包括操作系统内核
# commit命令
docker commit -a "automannn" -m "说明文字" <containerId> automannn:v1 # 将指定容器保存为新的镜像,并添加提交人信息和说明人信息
# cp命令
docker cp <containerId>:/app /app/ #将容器目录拷贝到主机
docker cp /app/ <containerId>:/app #将主机目录拷贝到容器
# 服务端镜像管理命令
# login/logout命令
docker login -u 用户名 -p 密码 [SERVER] #登录到docker仓库,如果未指定仓库地址,则默认未官方仓库 Docker Hub
docker logout #登出仓库,未配置,则默认为官方仓库
# pull命令
docker pull java #从官方仓库中,下载java最新镜像
# push命令
docker push automannn:v1 #上传本地镜像到仓库,需要先登录
# 推送到harbor仓库
# 如果是build 镜像,则可以直接指定,如
docker build . -t 192.168.10.7:20080/library/natm-natter:v1
docker push 192.168.10.7:20080/library/natm-natter:v1
# 如果是本地的已有镜像,则需先打tag
docker tag natm-natter:v1 192.168.10.7:20080/library/natm-natter:v1
docker push 192.168.10.7:20080/library/natm-natter:v1
# search命令
docker search java # 从镜像仓库中查找所有镜像名称包含java的镜像
# 本地镜像管理命令
# images命令
docker images #列出本地所有的镜像
# rmi命令
docker rmi -f automannn:v1 #强制移除automannn:v1本地镜像
# save命令
docker save -o automann_images.tar automann:v1 #将镜像生成tar文档
# load命令
docker load < automann_images.tar #导入tar镜像
# docker概览命令
# info命令
docker info #查看docker系统信息
# version命令
docker version #查看docker版本信息
# docker网络
- 安装docker时,会自动创建三个网络,分别为: bridge(容器默认连接到此网络)、none、host
- 该功能由 docker engine实现,它将在宿主机创建一个
docker0
的虚拟网桥;通过宿主机的创建虚拟网卡(一对,一端放在宿主机,一端放在容器中),并以该网桥为中介,形成一个二级网络.
# 网络模式的选择
docker run 启动Docker容器时,可以用 --net=选项 指定容器的网络模式
docker run aaa --net=host #指定host模式
docker run aaa --net=none #指定none模式
docker run aaa --net=bridge #指定bridge模式,默认选择此选项
docker run aaa --net=container:NAME_or_ID #与指定容器共享
# host模式
- 与宿主机共用一个network namespace,容器将不会虚拟自己的网卡等信息,而是直接使用宿主机的IP和端口,注意是使用,而非劫持;
# container模式
- 与其他容器共享一个network namespace,除网络外,文件系统、进程列表等还是隔离的.
# none模式
- 该docker容器会有自己独立的network namespace,但不会为docker进行任何网络配置。可借助pipwork工具为docker容器指定ip信息等
# bridge桥接模式
- 默认的网络模式
- 为每一个容器,自动分配一个独立的network namespace,默认将docker容器连接到虚拟网桥
docker0
上;
# Docker运行资源配置
通过命令docker container stats 容器id
可查看容器的资源使用情况
# 内存
# 命令
docker run -m 或者 --memory
设置内存的使用限额docker run --memory-swap
设置交换区swap限额 swap区是使用磁盘作为额外的内存(超过最大内存时),但是其速度较为缓慢,只能在合适的场景中使用
# 实例
docker run -m 100M --memory-swap 200M
表面该容器最大内存为100M,允许使用的交换区最大为200M
# 内存溢出处理
- 容器内存超出限制后,docker可能会将容器杀死
- 通过配置
--oom-kill-disable=false
可以保证容器不被docker杀死
# 缺省值
- 默认情况下,其参数为-1,即没有限制
# CPU
- 默认情况下,所有容器平等地使用CPU资源
- 可以通过
-c 或者 --cpu-shares
设置容器使用CPU的权重,默认值为1024;
# IO
- 默认情况下,所有容器能够平等地读写磁盘
- 通过参数
--blkio-weight
可改变容器IO的优先级,默认值为500.与CPU类似,它也是一个权重参数。
# Dockerfile镜像构建
# 功能特性
- 构建自定义镜像: 从基础镜像开始,通过命令,逐步添加所需的软件包,配置环境变量,设置工作目录等,形成一个完整的运行环境;
- 分层文件系统: 采用类似于git的分层文件系统技术, Dockerfile中的每条指令都会产生一个新的镜像层,这些层可以被共享和复用。
- 缓存机制: 每个构建步骤的结果都会被缓存,后续步骤如果未发生变化,则直接使用缓存结果,可以显著加速镜像的构建过程。
- 多阶段构建: 允许定义多个构建过程,每个阶段都可以有自己的基础镜像和构建步骤, 在最终的镜像中只保留必要的部分,减少不必要的文件和层,优化镜像大小;
- 透明性和可维护: 比
docker commit
创建的镜像具有更高的透明度和可维护性; Dockerfile本身就是一份详细的构建文档, 记录了镜像是如何一步步构建出来的。
# 指令集说明
- FROM: 指定基础镜像。
- RUN: 用于执行命令行命令。
- CMD: 指定容器启动时运行的命令,通常用于启动应用程序。
- EXPOSE: 声明容器内部的服务端口。
- COPY或ADD: 将主机中的文件或目录复制到镜像中。
- WORKDIR: 设置容器内的工作目录。
- ENV: 设置环境变量。
- VOLUME: 用于创建挂载点或声明卷。
- ENTRYPOINT: 设置容器启动时的主要命令,不可被覆盖。
# CMD与ENTRYPOINT的区别
CMD与ENTRYPOINT都是Dockerfile中的指令,它们都可以用来设置容器启动时要执行的命令。尽管两者有相似之处,但在功能和使用场景上存在一些关键区别。
CMD指令
CMD的主要用途是为容器提供默认的执行命令及其参数。这意味着当用户没有通过docker run
命令指定任何命令时,CMD中定义的命令将会被执行。然而,如果用户在运行容器时提供了命令行参数,那么这些参数会覆盖CMD中定义的内容 。
CMD有三种形式:
- 提供可执行文件及参数(exec form),这是推荐的形式。
- 作为ENTRYPOINT的默认参数(仅提供参数)。
- shell形式,这种形式会通过shell来执行命令(例如/bin/sh -c)。
例如,下面是一个使用CMD的例子:
FROM ubuntu
CMD ["ping", "localhost"]
如果你基于这个Dockerfile构建了一个镜像,并且在不带额外参数的情况下运行它,它将开始ping localhost。但是,如果你在docker run
命令后面指定了不同的命令,如docker run <image> hostname
,则CMD中定义的ping命令将被覆盖,而hostname将成为实际执行的命令 。
ENTRYPOINT指令
ENTRYPOINT的目的也是为了设置容器启动时要执行的命令,但它有一个重要的特性:一旦设置了ENTRYPOINT,除非使用--entrypoint
选项,否则该命令不会被忽略或覆盖。即使用户提供了额外的参数,这些参数也会作为ENTRYPOINT所指定命令的参数传递给它 。
ENTRYPOINT也有两种形式:
- exec形式,这同样是最推荐的形式。
- shell形式,类似于CMD的shell形式。
以下是一个ENTRYPOINT的例子:
FROM ubuntu
ENTRYPOINT ["ping"]
在这个例子中,无论你是否提供额外的参数,容器都会尝试运行ping
命令。如果你运行容器时不提供参数,比如docker run <image>
,它会报错因为缺少了必要的参数(即目标主机)。但如果你运行docker run <image> localhost
,它就会开始ping localhost 。
组合使用
一个常见的模式是同时使用CMD和ENTRYPOINT。在这种情况下,CMD通常用于提供ENTRYPOINT命令的默认参数。这样做的好处是,ENTRYPOINT可以保持不变,而CMD提供的参数可以根据需要轻松地被替换。例如:
FROM ubuntu
ENTRYPOINT ["ping"]
CMD ["localhost"]
当你运行容器时,如果不提供额外参数,默认会ping localhost。如果你想ping其他地址,只需在docker run
命令后加上那个地址即可 。
总结来说,CMD更适合作为容器启动时的默认行为,允许用户在运行时覆盖;而ENTRYPOINT更适合定义容器的核心功能,不允许轻易被覆盖,但可以通过CMD或其他方式为其提供参数。
# 个人理解
- Dockerfile可以大大降低镜像迁移成本;对于最终的环境而言,可以去除大量无效的依赖文件;
- 有利有弊,其环境的兼容性不如直接commit的情况,毕竟镜像体积在这里;
# build时配置代理
ARG HTTP_PROXY
ARG HTTPS_PROXY
ENV HTTP_PROXY=${HTTP_PROXY}
ENV HTTPS_PROXY=${HTTPS_PROXY}
# 可选:设置 NO_PROXY
ARG NO_PROXY
ENV NO_PROXY=${NO_PROXY}
docker build \
--build-arg HTTP_PROXY="http://proxy.example.com:8080" \
--build-arg HTTPS_PROXY="http://proxy.example.com:8080" \
--build-arg NO_PROXY="localhost,127.0.0.1" \
-t myimage .
- 也可直接写死参数,如:
ARG HTTP_PROXY
ARG HTTPS_PROXY
ENV HTTP_PROXY=192.168.10.7:7890
ENV HTTPS_PROXY=192.168.10.7:7890