前言

一直在用docker,没系统的捋一遍。这准备简历,所以重新弄一遍,本篇只涵盖使用的知识。后面会有实战部署笔记和底层技术。

什么是Docker

基本概念

流程:研发镜像(image)->上传到镜像仓库(Registry)->通过Docker引擎down下来->运行down下来的容器(container)

  • Docker是一个容器引擎,用于管理容器的声明周期

  • 容器:包含用于运行一个软件的环境(包含了目标软件运行所需的所有依赖)和需要运行的软件,镜像的实例

  • 镜像:容器的安装包,必须先有镜像,才能运行容器

  • 仓库:用于存放镜像,对镜像进行统一管理

打个比方:仓库是软件商店,镜像是软件安装包,容器是安装成功后的软件

Docker与虚拟机对比理解

对比

Docker的架构

C/S架构:Client客户端,Server服务端

Docker Client

Docker客户端,向服务端发起请求,比如下载镜像,管理容器声明周期

Docker Daemon

Docker的后台守护程序,包含:

  • Docker Server:服务端,接收请求

  • Engine:容器引擎,负责执行任务

Docker Registry

镜像仓库

Docker入门

基础命令

镜像

docker search jdk 用于查找jdk镜像的版本

docker pull openjdk:11 把jdk的镜像拉取到本地,冒号用于指定版本

docker images 查看本地镜像

docker rmi 123456 删除id号为123456的本地镜像

容器

docker ps 查看当前运行的容器

docker ps -a 查看当前所有容器名称

docker run [容器名称] 运行目标名称的容器,默认前台运行

前台运行vs后台运行

前台运行:启动容器时,将容器的输入输出与宿主机的终端相连,用户可以直接在当前终端与容器进行交互

后台运行:容器在后台独立运行,不与宿主机的终端直接关联。容器启动后,命令行会立即返回,你可以继续在宿主机终端执行其他操作

docker run -d -p 80:81 [容器名称] 运行目标名称的容器,-d指定后台运行,-p指定容器监听主机80端口,若有请求则转发到容器内81端口

因为资源隔离,所以容器内外网络不互通,eg内外都有80port,所以用到-p参数标识路由转发

docker run -d -P [容器名称] -P 参数的作用是让 Docker 自动在宿主机上选取一个可用的端口,并将其映射到容器内暴露(EXPOSE)的端口上,暴露端口指的是在Dockerfile里通过EXPOSE命令声明的容器内监听的端口

docker rm 123456 删除id为123456的停止的容器,id不一定为123456,只要123456能定位到一个唯一id的容器即可

docker rm -f 123456 强制删除id为123456的容器,无论是否运行中

docker stop 123456 停止id为123465的容器

docker start 123456 启动id为123456的容器

docker run -d -name cont01 [容器名称] 启动目标容器并指定名称为cont01,后续操作可用名字代替id

docker run --rm [容器名称] 运行容器,rm标识该容器停止后会自动删除

docker run -d --restart on-failure:3 [容器名称] --restart标识重启策略,默认不重启;on-failure失败时重启,可以加上:3表示第三次部署失败就不重启了;always表示只要已关闭就自动重启

docker run -d -P -e JAVA_ENV=dev -e JAVA_VM=G1 nginx 启动 nginx 容器时设置 JAVA_ENV=devJAVA_VM=G1 这两个环境变量

docker inspect NAME|ID 查看docker对象的详细信息

docker exec -it cont01 env exec命令是指定cont01容器,基于容器内终端(it),来执行env命令(显示环境变量)

-m 8m 限制内存最大为8mb,--cpus 1 限制cpu最多用一个

docker logs cont01 输出cont01容器的所有日志

docker exec -it cont01 bash 进入容器cont01内部,并使用bash

Docker进阶

数据卷Volume

基本概念

  • 是容器外部的独立存储空间,即使容器被删除,数据卷仍会保留。

  • 同一个数据卷可被多个容器同时挂载,所有容器对卷内数据的读写操作是实时同步的

  • 容器可通过数据卷直接访问宿主机文件系统,高性能

绑定方式

匿名绑定

docker run -v /app/data nginxDocker 自动创建无名称卷,存储路径为宿主机的 Docker 数据目录/volumes/随机哈希

  • 容器删除后卷仍然存在,需要手动清理

  • 容器启动时加 --rm,停止后卷会自动删除

具名绑定

docker run -d -v my-named-volume:/app/data my-image 不关心存放的位置,只想持久化存储一些内容

  • 有自定义的名字,能够轻松识别和管理卷

  • 除非手动删除,否则会一直存在

Bind Mount

把宿主机的目录直接映射到容器内的目录

docker run -v /host/path:/container/path my-image /host/path 是宿主机上的路径,/container/path 是容器内的挂载路径

  • 只要宿主机上的文件或目录存在,即使容器被删除,数据也不会丢失

  • 可以挂载宿主机上的任意文件或目录,不受 Docker 卷存储管理的限制

  • 宿主机和容器内的文件修改会实时同步

数据卷管理

1
2
3
4
5
6
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove unused local volumes
rm Remove one or more volumes

网络Network

基本概念

是什么

Docker对容器网络隔离的一项技术,提供了多种不同模式供用户使用,选择不同的网络模式来实现容器网络的互通以及的隔离

需求

  • 容器间的网络隔离

  • 实现部分容器之间的网络隔离

  • 管理多个子网下的容器ip

作用

  • 提供了多种模式,可以定制化的为每个容器制定不同的网络

  • 自定义网络模式,划分不同的子网|网关|dns等配置

  • 实现网络互通

    • 实现不同子网之间的网络互通

    • 基于容器名(主机名)的方式在网络内访问

网络模式

bridge桥接模式(默认模式)

在主机中创建一个Docker0的网桥,在Docker0创建一对虚拟网卡,有一半在主机上vethxxx,有一半在容器内eth0

bridgeMode

host模式

容器不再拥有自己的网络空间,而是直接与主机共享网络空间,基于该模式创建的容器对应的ip实际及时与主机为同一个子网,同一个网段

hostMode

none模式

Docker会拥有自己的网络空间,不与主机共享,在这个网络模式下的容器,不会被分配网卡&ip&路由等相关信息

  • 完全隔离,与外部任何机器都无网络访问,只与自己的io,本地网络127.0.0.1

  • 绝对安全

noneMode

Container模式

不会创建自己的网络,与其他容器共享网络空间,直接使用指定容器的ip/端口

containerMode

自定义网络模式(推荐)

不适用Docker自带的网络模式,而是自己定制化自己持有的网络模式

命令:docker network COMMOND

Manage networks

Commands:
  connect     Connect a container to  a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

为什么自定义网路中的容器能通过容器名ping通,但是bridge模式不行

Docker自定义网络中,DNS被深度集成以实现容器间的自动服务发现。当容器加入自定义网络时,Docker会将其容器名和ip地址注册到DNS服务器

bridge模式不嵌入DNS

不同模式下的链接

docker network connect wolfcode net1

contactBetweenTwoDifferentMode

Dockerfile文件

基本概念

是什么

  • 构建镜像用的

  • Docker为我们提供的一个用于自定义构建镜像的一个配置文件:描述如何构建一个对象

  • 利用Docker提供的build命令,指定Dockerfile文件,就可以按照配置的内容将镜像构建出来

为什么需要

  • 作为开发者,需要将自己开发好的项目打包成Docker镜像,便于后面直接作为Docker容器运行

  • 作为运维人员,需要构建更精简的基础设施服务镜像,满足公司的需求以及尽可能减少冗余的功能占用过多的资源

能做什么

  • 可以自定义镜像内容

  • 构建公共基础镜像减少其他镜像配置

  • 开源程序快速部署

  • 实现企业内容项目快速交付

常用指令

FROM

指定以什么镜像为基础镜像,在改进项的基础之上构建新的镜像

如果不想以任何镜像为基础:FROM scratch

语法:

  • FROM <image>

  • FROM <image>:<tag>

  • FRom <image>:<digest>

以上三种写法,后两者为指定具体版本,第一种则使用latest也就是最新版

MAINTAINER

指定镜像的维护者

MAINTAINER John Doe <johndoe@example.com> 

MAINTAINER 指令指定了镜像的维护者是 John Doe,其邮箱为 johndoe@example.com

Docker官方现已弃用MAINTAINER命令,他的功能可以用LABEL指令更灵活的实现

LABEL

为镜像|容器|卷添加元数据

语法

  • LABEL <key>=<value> <key>=<value> <key>=<value> ...

可以在一条 LABEL 指令中定义多个键值对,也能使用多条 LABEL 指令。键值对之间用空格分隔,键和值之间用等号连接

eg

LABEL maintainer="John Doe <johndoe@example.com>"

ENV

设置容器的环境变量,可以设置多个

语法:

  • ENV <key> <value>

  • ENV <key>=<value> <key>=<value>...

RUN

RUN 指令在构建镜像期间执行,在 Dockerfile 中可以有多个 RUN 指令,每个 RUN 指令都会在镜像中创建一个新的层。为了减少镜像的层数和体积,建议将相关的命令组合在一个 RUN 指令中执行

语法:

  • RUN <command>

  • RUN ["executable","param1","param2"]

第一种写法直接写shell脚本即可

第二种写法类似于函数调用,第一个参数为可执行文件,后面的都是参数

eg

RUN ["/bin/bash", "-c", "echo hello"]

-c 后面跟着的 "echo hello" 会被当作 shell 命令来执行,所以直接调用 /bin/bash 来执行 echo hello 命令

ADD

复制命令,把src的文件复制到镜像的dest位置(从主机复制到容器)

语法:

  • ADD <src> <dest>

  • ADD ["<src>","<dest>"

WORKDIR

设置并cd到容器中的工作目录,如果该目录不存在则自动创建。

语法:

  • WORKDIR /app

在根目录下创建app目录

VOLUME

设置挂载目录,可以将主机中的指定目录挂载到容器中

语法:

  • VOLUME ["<dir>"]

  • VOLUME <dir>

  • VOLUME <dir> <dir>

EXPOSE

设置容器启动后要暴露的端口(容器在运行时会监听的网络端口)

语法:

  • EXPOSE <port> [<port>/<protocol> ...]

<port>表示容器要监听的端口号,<protocol>是可选参数,用于指定端口使用的协议,默认值为 tcp,也可以设置为 udp

注意:EXPOSE只是暴露端口,并没有与主机的端口形成映射。映射行为是在容器run的时候加-p参数实现的

CMD

CMD 指令在容器启动时执行,在 Dockerfile 中只能有一个 CMD 指令,若有多个 CMD 指令,只有最后一个会生效

语法:

  • CMD echo "Hello world!"

  • CMD ["echo","Hello world!"]

ENTRYPOINT

用来设置容器启动时要执行的命令,并且这个命令不能被 docker run 后面的参数直接覆盖,它提供了一种固定容器启动行为的方式,常用于设置容器的主命令

CMDENTRYPOINT的区别

  • 单独使用 ENTRYPOINTdocker run 后面添加的参数会被当作 ENTRYPOINT 命令的参数

  • 单独使用 CMD,如果 docker run 后面添加了其他命令,CMD 指定的命令会被覆盖

  • ENTRYPOINTCMD 结合使用时,CMD 提供的参数会作为 ENTRYPOINT 命令的默认参数,若 docker run 后面添加了参数,这些参数会替换 CMD 的默认参数

构建镜像

commit

基于一个现有的容器,构建一个新的镜像(image)

定制化操作不方便!

build

自己构建两个镜像练练手

eg

# 使用Python 3.9作为基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制当前目录下的所有文件到工作目录
COPY . /app

# 安装应用所需的依赖
RUN pip install --no-cache-dir -r requirements.txt

# 暴露应用运行的端口
EXPOSE 5000

# 设置环境变量
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0

# 定义容器启动时执行的命令
CMD ["flask", "run"]

仓库Registry

  • 用于管理Docker的镜像

  • 快速交付

  • 便于镜像的重复利用

registry

常见仓库

  • Docker Hub

  • Aliyun

  • Nexus

  • Harbor

容器编排

这块没啥理论上的,实际部署一下就会了

针对容器声明周期的管理,对容器声明周期进行更快速方便的方式进行管理

  • 依赖管理,当一个容器必须在另一个容器运行完成后才能运行时,就需要进行依赖管理

  • 副本数控制,容器有时候也需要集群,快速对容器集群进行弹性伸缩

  • 配置共享,通过配置文件统一描述需要运行的服务相关信息,自动化的解析配置内容,并构建对应服务

更简单的使用容器

Docker Compose(单机)

  • 基于构建好的镜像来创建和管理多个容器

  • 需求:在一台机器上部署多个容器

  • Docker-Compose可以高效便捷的管理单机上运行的所有容器,通过yaml配置文件的方式完成之前执行docker run命令所设置的所有参数。

dockerCompose

服务services

需要运行的容器配置,可以理解为原先用docker run命令后面跟的一系列配置信息,都配在这里面

网络networks

docker-compose公共自定义网络管理,配置好以后,可以直接在services中引用该网络配置,这个配置可以多个services使用

数据卷volums

docker-compose下的统一数据卷管理,可以给多个services使用

Swarm(分布式)

docker的公司写的,与k8s竞争

Portainer可视化工具

很推荐啊,天天只在命令行docker来docker去,快docker抑郁了

PS C:\Users\flypiggy> docker --version
Docker version 28.0.1, build 068a01e
PS C:\Users\flypiggy> docker volume create portainer_data
portainer_data
PS C:\Users\flypiggy> docker run -d -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
Unable to find image 'portainer/portainer-ce:latest' locally
latest: Pulling from portainer/portainer-ce
e2e06b27b87e: Pull complete
1fed1531b45b: Pull complete
04de093ad5ed: Pull complete
86a7cce72d42: Pull complete
e09df2601140: Pull complete
eae3ebf29ea8: Pull complete
c12aa3fbd31a: Pull complete
f111bda3f9a6: Pull complete
81021110ed01: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:7f10a26bfdda3fc58295ea09b860117ecd86a642d66fb94ce1f27a4c221d4649
Status: Downloaded newer image for portainer/portainer-ce:latest
61cbab51c68ba3134921a2d7beb1ce320716682cac10f2094c0f08f3ae01c4d8