docker
docker
1. 介绍
docker是加速用户构建、分享、运行应用程序的平台- 构建:通过
docker pull命令将docker镜像下载到本地,通过docker run命令构建容器 - 分享:通过
docker build打包本地容器,之后使用docker push发布到应用市场中

docker的主要命令和执行过程 - 构建:通过
容器类似轻量级系统,每个容器之间相互隔离,共享操作系统的内核,可以方便地实现快速跨平台部署
2. 安装
2.1 window版本
- 家庭版需要开启Hyper-V
# 家庭版,不存在Hyper-V功能将以下命令存入cmd格式的文件中,以管理员权限运行,最后按y重启
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL
# 专业版,管理员权限运行powershell,输入此命令
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All检查
cpu是否开启虚拟化,可以在任务管理器查看
虚拟化查看方法 安装wsl
wsl --update- 设置docker引擎选择
# 重启docker服务(可以不进行)
Net stop com.docker.service
Net start com.docker.service
# 家庭版执行失败了,可以打开应用,但无法使用此命令,未解决
.\DockerCli.exe -SwitchDaemon2.2 ubuntu版本
- 安装方法参考,阿里云文档见docker-ce镜像,docker-ce下载地址,docker-ce安装教程,阿里巴巴开源镜像站
安装依赖
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release添加阿里云docker镜像
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null安装docker
sudo apt update # 安装docker套件,至少安装docker-ce sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 通过此命令设置开机自启动 systemctl enable docker配置容器下载镜像源
sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": [ "https://docker.m.daocloud.io", "https://docker.1ms.run", "https://docker.xuanyuan.me", ] } EOF # 重启docker服务 sudo systemctl daemon-reload sudo service docker restart安装检查
# 查看docker版本 docker version # 测试安装运行Hollow World容器 docker run hello-world
3. 常用操作
3.1 镜像管理
在应用商店中,一个镜像由仓库名称和版本号共同指定,比如
nginx:1.26.0,下载时也支持只提供仓库名或使用nginx:latest,将自动下载最新版本的镜像文件docker自带一个搜索命令,但由于国内无法正常使用搜索功能,且搜索结果描述不多,推荐先在docker hub搜索查看(同样无法国内直连)
# 搜索镜像,国内无法访问 docker search nginx # 下载镜像 docker pull nginx # 查看所有镜像,包括镜像名和镜像id等信息 docker images # 删除指定的镜像,支持通过镜像或镜像id删除 docker rmi nginx:latest
3.2 容器管理
容器查询
# 查看运行中的容器,-a表示查看所有容器,-q表示只显示id docker ps # 查询到的信息包括容器id、名称、创建时间、启动命令等在容器执行之后,
docker会分配一个容器名和一个在每次启动都可能变化的id作为容器标识,所有指向容器的命令都用容器标识来指定唯一的容器容器执行:相对于创建了一个小的文件系统,可以认为所有容器有独立的操作系统,互不影响
# 完整命令为docker run [启动选项] 镜像 [启动行为] [附加参数] # 一般情况下启动行为和附加参数在镜像中的配置好了,一般不需要设置 # -d:后台启动,默认会作为程序前置启动 # --name test_name:为容器取名test_name # --network 网络名:加入自定义网络 # -p 88:80:容器的80端口映射到主机88端口 # -e 添加环境变量k=v的格式 # -v /dict:/usr/share/nginx/html:将目录挂载到本地dict目录 # 挂载相当于将对应路径改成了主机路径,内部的文件并不会复制到外部 # -V ngxconf:/etc/nginx:卷映射,保留内部文件,在外部为附加卷 # 卷路径统一放在了/var/lib/docker/volumes/下 # 删除容器后挂载和卷都不会删除 # 运行一个新容器,如果镜像不存在会先下载 docker run nginx # 如果希望之后再启动容器,可以通过容器id或随机容器名启动 # 容器id和git的commit id一样,在指定容器时id不需要完整输入,只需要确保能够识别唯一容器就行 # 启动容器 docker start 容器标识 # 停止容器 docker stop 容器标识 # 重启容器 docker restart 容器标识 # 如果希望进入容器,修改内容,最后一个参数指明使用的应用,比如是命令行 docker exec -it 容器标识 bash其他命令
# 删除指定容器,可以通过-f强制删除正在执行的容器 docker rm 容器标识 # 删除所有容器 docker rm $(docker ps -aq) # 查看容器资源占用情况 docker stats 容器标识 # 查看容器日志 docker logs 容器标识 # 查看容器细节 docker inspect 容器标识
3.3 镜像发布
# 提交容器变化打包成一个新的镜像
docker commit -m "提交信息" 容器标识 仓库名:版本号
# 保存镜像为指定文件
docker save -o output.tar 镜像
# 加载镜像
docker load -i output.tar
# 登录docker hub
docker login
# 重新给镜像打符合规范的标签,要上传的镜像名称中应该包含用户名
docker tag 镜像 用户名/仓库名:版本号
# 推送镜像
docker push 用户名/仓库名:版本号3.4 卷管理
在容器启动时,可以通过添加
-V参数挂载内部文件夹到外部卷中,这些卷可以在外部查看和管理# 查看所有卷 docker volume ls # 创建空卷 docker volume create 卷名 # 删除卷 docker volume rm 卷名 # 检查卷 docker volume inspect 卷名
3.5 容器通信网络
在
docker中,容器向外部的通信可以通过端口映射完成,容器和容器的通信可以通过docker0完成,docker0是docker的内部网络,每个容器都会被分配一个ip,可以用于完成通信# 查看ip docker inspect 容器 # 通过内部ip和容器端口通信使用
docker0进行通信很好,但ip可能发生变化,而docker0不支持自定义域名。如果需要进行容器间通信,一般会在容器创建前先创建一个网络# 创建网络 docker network create 网络名 # 将创建的容器加入自定义网络 docker run --network 网络名 nginx # 直接通过容器名称作为域名就可以访问对应的容器 # 使用docker exec进入container2后,访问container1的80端口 curl https://container1:80
4. compose
docker提供了批量创建容器的方法,通过yaml文件配置,就可以批量完成容器创建compose.yaml支持增量更新,修改文件只会触发相关容器重启- 支持所有
run支持的功能,包括卷、端口映射等
需要提供的顶级名称如下:
name:部署名称services:服务,对应容器,配置run命令支持的可选项network:创建的网络volumns:所有要使用到的卷config:配置项secrets:秘钥
注意,服务、网络和卷定义时都不是通过列表的形式书写(开头没有
-)name: test services: mysql: container_name: mysql image: mysql:8.0 ports: - "3306:3306" environment: # 环境变量也可以使用非列表配置(不在前面加-) - MYSQL_ROOT_PASSWORD=123456 - MYSQL_DATABASE=db1 volumes: - mysql-data:/var/lib/mysql - /app/myconf:/etc/mysql/conf.d restart: always networks: - test_network # 支持设置depands_on依赖关系决定启动顺序 # depands_on: # - other_service_name1 # - other_service_name2 volumes: mysql-data: network: test_network:使用
yaml文件# 上线,-d表示后台启动 docker compose -f compose.yaml up -d # 停止 docker compose -f compose.yaml stop # 启动 docker compose -f compose.yaml start # 下线,删除 docker compose -f compose.yaml down
5. Dockerfile
Dockerfile是docker的构建文件,名称固定,因为每次构建镜像前的准备工作可能很多,因此使用构建文件清单,避免重复构建时的输入的大量命令在目录下创建了这个文件后,可以使用
docker build -t 镜像名:标签 文件所在目录的方式进行构建docker build -t my-nginx:1.0 . # 命令执行应该带有 -t 选项指明镜像名称和标签 # 不然将得到虚悬镜像(无名称和标签),当然 build 和 rmi 失败时也可能产生虚悬镜像 # 查看所有的虚悬镜像 docker images ls -f dangling=true # 删除所有虚悬镜像 docker image prune
5.1 构建流程
Dockerfile的内容包含许多条指令- 每条保留字指令名应该全大写,且至少跟随一个参数
- 指令从上到下,顺序执行
#用于表示注释- 每条指令都会创建一个新的镜像层并对镜像进行提交
镜像层是不可变的,代表文件系统的变更。这些层通过合并形成最终的统一的文件系统(镜像),类似无法回滚的单线操作历史记录,使用
docker history 镜像名命令查看镜像的构建历史docker build命令的执行流程大致为- 从基础的镜像运行一个容器
- 执行一条指令,对容器做出修改
- 执行类似
commit的镜像提交操作,提交一个新的容器层 - 再基于刚提交的镜像运行一个容器,执行
Dockerfile中的下一条指令直到所有指令都执行完成
5.2 保留字指令
- 在
Dockerfile中,常用保留字指令有: FROM:指定基础镜像,必须的作为第一条的指令,比如FROM ubuntu:18.04RUN:在容器内终端执行一条命令,可以使用命令行格式或exec格式- 命令行格式:
RUN <command>,比如RUN mkdir /app exec格式:RUN ["executable", "param1", "param2"],比如RUN ["cp", "file1", "/app"]
- 命令行格式:
MAINTAINER:指定镜像的作者和邮箱,非必须,格式MAINTAINER <NAME> <<EMAIL>>EXPOSE:指定容器对外暴露的端口,格式EXPOSE <port> ...,比如EXPOSE 80 3306WORKDIR:指定镜像的shell登录目录,格式WORKDIR <dir>ENV:设置环境变量,格式ENV <key> <value>- 也可以使用
=代替键值间的空格,比如ENV PATH=/app/bin - 设置了变量之后可以使用
$key来引用变量,比如WORKDIR $PATH
- 也可以使用
USER:指定镜像的运行用户,格式USER <user>,一般不修改,默认是rootVOLUME:创建一个挂载点,格式VOLUME <dir>,之后在启动容器时可以在这个位置进行挂载- 如果用户没有挂载,那
docker会创建一个匿名卷挂载到这个位置
- 如果用户没有挂载,那
ADD:将主机或网络文件添加到镜像中,格式ADD <src> <dest>,比如ADD file1 /app/file1- 命令会自动处理网络地址,进行请求,等同于
RUN curl -o <dest> <src> - 命令会自动解压
tar包 - 如果不需要这些功能,应该使用
COPY file1 /app/file1指令
- 命令会自动处理网络地址,进行请求,等同于
CMD:指定容器启动时执行的命令,格式和RUN一致,只有最后一个CMD指令才生效,示例CMD ["python", "app.py"]- 此命令对应
docker run nginx /bin/bash中的/bin/bash部分,会被启动时的指令覆盖
- 此命令对应
ENTRYPOINT:指定容器启动时执行的命令,格式和CMD一致,也只有最后一个生效,区别在于不会启动命令run中添加的指令覆盖,示例ENTRYPOINT ["python", "app.py"]- 虽然能和
CMD一起使用,但无论什么形式,都只能有一行命令,两个指令部分会按顺序拼接起来执行 - 一般将
ENTRYPOINT放在最前面指定程序和固定参数,CMD放在最后面作为可变参数
- 虽然能和
6. 原理
6.1 unionFS
unionFS联合文件系统:是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层地叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下union filesystem是docker镜像的基础,使镜像可以通过分层来进行继承,制作各种具体的镜像- 特性是一次同时加载多个文件系统,但从外界看来,只能看到一个文件系统,因为联合加载会把各层文件系统叠加起来,这样最终的文件像是在一个文件系统下
