写完 Kubernetes
的笔记, 再回头来补充 Docker
的笔记。
简介
Docker helps developers build, share, run, and verify applications anywhere — without tedious environment configuration or management.
Docker 可以帮助开发人员在任何地方构建、共享、运行和验证应用程序,无需繁琐的环境配置或管理。
这是官网对 Docker 的最有力而且简明的介绍。
就像他的小鲸鱼图标, 背着很多的集装箱, 每个集装箱装着一个应用, 里面包含了不同的集装箱含有配置文件, 启动命令, 应用程序及环境变量, 第三方依赖, 运行时环境和操作系统等。运送到任何一个可以执行应用的地方.
Docker 和虚拟机的区别
Docker 和虚拟机都是虚拟化技术, 都可以解决应用运行环境不匹配的问题, 但是 Docker 是轻量级的虚拟化技术, 虚拟机是重量级的虚拟化技术, Docker 的优势是轻量级, 虚拟机的优势是可移植性。
如下图:
虚拟化技术是一种将物理资源虚拟为多个逻辑资源的技术, 每个虚拟机都分配有独立的 CPU, 操作系统, 内存, 硬盘和网络接口等等, 虚拟机之间是隔离且独立的. 这样一来, 可以将多个物理服务器分配给多个逻辑服务器. 但缺点也很明显, 尤其是安装了操作系统. 但多数时候, 我们只需要一个对外服务的 App 而已, 所以 Docker 就出现了. 他将上面虚拟机的结构简化成了容器(Container):
Docker 是一个开源的容器化技术. 自身包含了操作系统
Docker 的基本架构
他是一个 C/S 架构的系统, 客户端通过 Docker CLI 与 Docker Engine 通信, Docker Engine 是一个轻量级的进程管理工具, 它运行在主机上, 负责管理 Docker 容器的生命周期.
我们和 Dokcer 打交道, 都是通过 Client 客户端的, 通过图形化界面或者敲命令, 服务端我们一般接触不到的. 服务端帮我们处理这些我们发出的命令, 然后将结果返回给我们而已.
而我们制作好的镜像, 通过 docker push
上传到 Docker Hub (Registry) 仓库上, 然后通过网络 docker pull
下载到本地.
安装
这里安装其图形化界面, 我用的是 M1 的 Mac
windows 运行前需要开启 HyperVisor
功能
镜像(Image) 和 容器(Container) 两个重要概念
- Docker 镜像(Image):镜像是一个只读的模板,可以用来创建容器;
- Docker 容器(Container):容器是镜像的运行实例,它是一个独立的环境,可以在这个环境中运行应用程序,一个镜像可以创建多个容器;而我们上面提到的仓库是用来存储 Docker 镜像的地方,比如 DockerHub,我们可以在这里下载各种镜像,也可以将自己的镜像上传到这里。
命令操作
命令在实际项目中应用不多, 项目中我们经常用 Dockerfile
如何设计到集群, 我们还会使用 Kubernetes
( 关于 Kubernetes
可参考这篇文章), 但命令还需要掌握一下的, 这里分为镜像命令和容器命令
镜像命令
搜索
1 2 3
| docker search [image]
docker search --limit 5 nginx
|
拉取和上传
1 2 3 4 5
| docker push [image]
docker push zyzy/nginx:lastest docker push registry.cn-beijing.aliyuncs.com/zhangsan/nginx:1.0
|
查看本地镜像
1 2 3 4
| docker images
docker image ls
|
删除镜像
1 2 3
| docker rmi [image]
docker image rm [image]
|
构建
1 2 3 4 5 6
| docker build -t [image]:[tag] [path]
docker build -t zhangsan/nginx:latest .
docker build .
|
其他命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| docker history [image]
docker load -i [file]
docker load -i nginx.tar
docker save [image] > FILE
docker save [image] -o FILE
docker save zhangsan/hello-docker:latest > hello-docker.tar
|
容器命令
列出所有正在运行的容器
1 2 3
| docker ps
docker container ls
|
列出所有容器
1 2 3
| docker ps -a
docker container ls -a
|
仅创建
创建并运行
1 2 3 4
| docker run -d -p [host port]:[container port] [image]
docker run -d -p 80:80 zhangsan/nginx:latest
|
参数:
-d
: 运行容器并进入后台
-p
: 映射端口
-it
: 运行容器并进入交互模式
-a
: 运行容器并进入交互模式, 并且保持 STDIN 打开并允许 tty 控制
-w
: 指定容器工作目录
-v
: 挂载卷
-e
: 设置环境变量, 如: docker run -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=test -e MYSQL_USER=test -e MYSQL_PASSWORD=123456 mysql:5.7
--net="bridge"
: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
--rm
: 容器退出后自动删除容器文件
下面, 给出一些示例:
1 2 3 4 5
| docker run -it --rm [image] [COMMAND] /bin/bash
docker run -d -p [hostPort]:[containerPort] -e [key=value] -w [PATH] --name [name] [image]
|
运行, 暂停, 重启
1 2 3
| docker start [container] docker stop [container] docker restart [container]
|
进入容器
1 2 3
| docker exec -it [container] [command]
docker exec -it zhangsan/nginx:latest /bin/bash
|
删除容器
1 2 3
| docker rm [container]
docker container rm [container]
|
查看容器 CPU 和内存占用情况
1
| docker stats [container]
|
其他容器命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| docker export [container] -o FILE
docker export [container] > FILE
docker import FILE
docker logs [container]
docker port [container]
docker top [container]
docker cp [FILE] [container]:[PATH]
docker diff [container]
|
数据卷管理
数据卷(Data Volumes)是一个可供一个或多个容器使用的特殊目录,它绕过了 UFS,可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 数据卷默认会一直存在,即使容器被删除
- 数据卷会一直存在,直到没有容器使用
Docker Volume 本质上是容器与主机之间共享的目录或者文件,这样 Docker Volume 中的数据可以在主机和容器中实时同步。
由于容器很容易被销毁, 所以持久化的数据, 即 DB 的数据, 我们必须挂载在本地电脑上, 会自动挂载到容器中, 容器销毁后, 数据还在.
创建
1 2 3
| docker volume create [volume]
docker volume create zhangsan-volume
|
查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| docker volume ls
docker volume inspect [volume]
(base) zyzy:~ $ docker volume inspect minikube [ { "CreatedAt": "2024-05-25T13:07:07Z", "Driver": "local", "Labels": { "created_by.minikube.sigs.k8s.io": "true", "name.minikube.sigs.k8s.io": "minikube" }, "Mountpoint": "/var/lib/docker/volumes/minikube/_data", "Name": "minikube", "Options": {}, "Scope": "local" } ]
|
删除
1 2 3 4
| docker volume rm [volume]
docker volume prune
|
维护管理命令
1 2 3 4 5 6 7 8 9 10 11
| docker version docker [command] --help docker info
docker system prune
docker login
docker logout
|
网络命令
Docker 默认会创建三个网络,分别是 bridge、host、none。
网络模式:
- bridge:桥接网络,Docker 默认使用的网络模式,使用 docker run 命令创建容器时如果不指定网络模式,那么就会使用 bridge 模式。
- host:主机网络,使用宿主机的网络,容器将不会获得一个独立的网络命名空间,配置和宿主机共享,容器将不会隔离宿主机网络,使用宿主机的 IP 和端口。
- none:无网络、禁用网络,容器拥有自己的网络命名空间,但是并不为容器进行任何网络配置,这个网络模式的容器只适合于只进行数据处理,没有任何网络的应用场景。
- container:容器网络,使用其他容器的网络,指定使用其他容器的网络栈。
- overlay:跨主机网络,用于跨多个 Docker 守护进程的容器通信,Docker 1.9 版本中增加的功能。
- macvlan:通过 MAC 地址绑定来实现容器访问外部网络,Docker 1.12 版本中增加的功能。
- ipvlan:通过 IP 地址绑定来实现容器访问外部网络,Docker 1.12 版本中增加的功能。
命令:
1 2 3 4 5 6 7 8 9 10 11 12 13
| doocker network ls
docker network inspect [network]
docker network create [network]
docker network rm [network]
docker network connect [network] [container]
docker network disconnect [network] [container]
|
插件管理
插件是 Docker 1.13 版本中引入的功能,它可以扩展 Docker 的核心功能,比如网络、存储、日志等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker plugin ls
docker plugin inspect [plugin]
docker plugin install [plugin]
docker plugin install traefik
docker plugin enable [plugin]
docker plugin disable [plugin]
docker plugin rm [plugin] docker plugin disable [plugin]
|
Dockerfile
有点像 shell 脚本,但是语法比 shell 脚本简单.
Dockerfile 中包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
Dockerfile 中的指令不区分大小写,但是为了可读性,建议使用大写。
Dockerfile 中的指令按照从上到下的顺序执行。
Dockerfile Instruction
FROM
:指定基础镜像,必须为 Dockerfile 文件的第一条指令;
MAINTAINER
: 指定镜像的维护者,可以为个人、公司、组织等;(可省)
ADD
: 用于将文件拷贝到镜像中,源可以是 URL 或者本地文件,也可以是一个压缩文件(自动解压);
COPY
: 用于将文件拷贝到镜像中,源只能是本地文件;
WORKDIR
: 用于指定工作目录,后续的指令都会在该目录下执行;
ENV
: 设置环境变量;
EXPOSE
: 指定容器的端口号,用于映射到主机的端口号;
RUN
: 用于执行命令,可以执行任何命令,比如安装软件、编译代码、启动服务等;
1
| RUN apt-get install -y nginx
|
CMD
: 用于指定默认的容器主进程,每个 Dockerfile 中只能有一条 CMD 指令,如果有多条,则只有最后一条会生效;
1
| CMD ["node", "/app/index.js"]
|
ENTRYPOINT
: 用于指定默认的容器主进程,每个 Dockerfile 中只能有一条 ENTRYPOINT 指令,如果有多条,则只有最后一条会生效;
VOLUME
:用于指定持久化目录,Docker 容器中的数据不会保存在镜像中,当容器删除时,数据也会随之删除;
USER
:用于指定运行容器时的用户名或 UID,后续的 RUN、CMD、ENTRYPOINT 指令都会使用该用户;
HEALTHCHECK
:用于指定检查容器健康状况的命令,如果检查结果不是 0,则认为容器不健康,从而终止容器运行;
ONBUILD
:用于指定当构建一个被继承的 Dockerfile 时需要运行的命令,父镜像在被子继承后,父镜像中的 ONBUILD 指令会被执行;
LABEL
:用于为镜像添加元数据,可以使用多个 LABEL 指令。
STOPSIGNAL
:用于指定停止容器时发送的系统调用信号;
SHELL
:用于指定默认的 SHELL 类型,可以使用多个 SHELL 指令。
ARG
:用于指定构建参数,构建参数可以在构建时使用–build-arg =来指定。
ENTRYPOINT
和 CMD
的区别
共同点: 都是在指定的容器启动程序及参数
不同点:当指定了 ENTRYPOINT 后,CMD 命令会作为参数传递给 ENTRYPOINT,ENTRYPOINT 命令作为主进程运行,CMD 命令作为参数传递给主进程。
以上阐述可能比较难懂,我们通过一个实例来理解:
- 创建一个 Dockerfile 文件,内容如下:
1 2 3
| FROM ubuntu:latest RUN apt update && apt install curl -y CMD [ "curl", "-s", "http://ipinfo.io/ip" ]
|
可以看到内容很简单,就是安装 curl,然后执行 curl -s http://ipinfo.io/ip 命令。
- 构建镜像:
1 2 3 4
| (base) zyzy:~ $ docker build -t ubuntu-curl-demo . (base) zyzy:~ $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu-curl-demo latest 61b1bfbc1cf6 3 hours ago 122MB
|
- 运行容器:
1 2 3
| (base) zyzy:~ $ docker run ubuntu-curl-demo 202.81.228.36%
|
CMD
命令假如运行容器时,加入参数,就会发生报错:
因为参数 -I
会覆盖 CMD
原来的全部参数,因此报错:
1 2 3 4
| (base) zyzy:~ $ docker run ubuntu-curl-demo -I docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-I": executable file not found in $PATH: unknown. ERRO[0000] error waiting for container: context canceled
|
- 将原来 dockerfile 中的 CMD 命令改为 ENTRYPOINT 命令,重新构建镜像:
1 2 3
| FROM ubuntu:latest RUN apt update && apt install curl -y ENTRYPOINT [ "curl", "-s", "http://ipinfo.io/ip" ]
|
- 运行新的 curl-demo 容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| (base) zyzy:~ $ docker build -t curl-demo . (base) zyzy:~ $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE curl-demo latest 61b1bfbc1cf6 4 hours ago 122MB
(base) zyzy:~ $ docker run curl-demo -I HTTP/1.1 405 Method Not Allowed allow: GET, OPTIONS connection: close content-length: 18 content-type: text/plain; charset=utf-8 date: Tue, 09 Apr 2024 14:09:24 GMT server: nginx/1.24.0 strict-transport-security: max-age=2592000; includeSubDomains via: 1.1 google x-envoy-upstream-service-time: 0
|
Docker Compose
Docker Compose 是由 Docker 官方开源的项目,用于定义和运行多个 Docker 容器应用程序的工具。(Defining and running multi-container Docker applications)比如我们如果想要搭建一个网站的话,可能会用到前端、后端、数据库、甚至缓存和负载均衡等多个服务,这些服务都是独立的,但是它们之间又是有关联的,需要相互配合工作,比如后端需要连接数据库,前端需要连接后端,这些服务之间的关联关系就是 Compose 要解决的问题。它通过一个单独的 docker-compose.yml 配置文件来将这一组相互管理的容器组合在一起。
Docker Compose 使用一个命名为 docker-compose.yml 的 YAML 文件来配置应用程序的服务,YAML 文件中包含了应用程序的配置信息,比如服务、网络、卷等。
启动一个应用程序时,只需要运行 docker-compose up 命令,Docker Compose 就会自动去查找当前目录下的 docker-compose.yml 文件,并根据这个文件来启动应用程序的所有服务。
当你不再需要这个应用程序时,只需要运行 docker-compose down 命令,Docker Compose 就会停止并删除所有容器、网络、卷等。