docker 原理与简单操作
一、讨论
- 有没有用过 docker
- 用来做什么
- 你想通过这次分享了解到 docker 的那些知识点
环境 中间件 无法快速复制
二、概念
Docker 是基于 go 语言开发。
2013 年 docker 开源,2014 年 docker 发布 1.0 版本。
在容器化技术流行起来之前,大家使用的基本都是虚拟化技术 Vmware 等。
虚拟化技术基本上是运行一个全新的操作系统,虚拟化网卡 cpu gpu 等,中间会带来大量的性能损耗,且由于需要虚拟化整个操作系统,导致占用空间非常大,得不偿失。
那么有没有一个既能做到隔离,又十分小巧的技术呢?
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。
容器是完全使用沙箱机制,容器性能开销极低。
Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。
Docker 的可移植性和轻量级的特性,还可以轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。
三、快速运行一个容器
-
首先安装 docker 服务
官方网站 https://www.docker.com/products/docker-desktop/
docker hub https://registry.hub.docker.com/
-
拉取一个镜像
这里是一个我提供的一个基于 nginx 的小网页
# 拉取镜像
docker pull czqclm/easy-nav:latest
# 查看当前镜像
docker images
docker image ls
-
运行一个镜像
# 运行镜像
docker run czqclm/easy-nav:latest --name nginx
# 后台运行镜像
docker run -d czqclm/easy-nav:latest --name nginx
-
进入容器
docker exec -it nginx bash
exit;
-i
以交互模式运行容器
-t
为容器重新分配一个伪输入终端
-d
后台运行容器
-
停止容器
docker stop nginx
docker rm nginx
-
一些组合用法
docker run \
-p '40081:80' \
--restart always \
--name nginx \
-d czqclm/easy-nav:latest
http://4c4g.lolkeyking.top:40081/
增效了,但没完全增
还是需要写大量的脚本,手动部署等。
四、使用 docker-compose
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
安装 https://docs.docker.com/compose/install/
概念:project service container
编写文件 docker-compose.yml
version: '3'
services:
nginx:
image: czqclm/easy-nav:latest
restart: always
container_name: nginx
ports:
- '40081:80'
docker-compose up -d
docker-compose down
参考 yaml
Ekl
version: '3'
services:
elasticsearch:
image: elasticsearch:7.6.2
container_name: elasticsearch
privileged: true
environment:
- "cluster.name=elasticsearch" #设置集群名称为elasticsearch
- "discovery.type=single-node" #以单一节点模式启动
- "ES_JAVA_OPTS=-Xms512m -Xmx512m" #设置使用jvm内存大小
volumes:
- /volume1/docker/elk/elasticsearch/plugins:/usr/share/elasticsearch/plugins #插件文件挂载
- /volume1/docker/elk/elasticsearch/data:/usr/share/elasticsearch/data #数据文件挂载
ports:
- 49200:9200
- 49300:9300
logstash:
image: logstash:7.6.2
container_name: logstash
privileged: true
environment:
- TZ=Asia/Shanghai
volumes:
- /volume1/docker/elk/logstash:/usr/share/logstash/pipeline #挂载logstash的配置文件
depends_on:
- elasticsearch #logstash在elasticsearch启动之后再启动
links:
- elasticsearch:es #可以用es这个域名访问elasticsearch服务
ports:
- 44560:4560
kibana:
image: kibana:7.6.2
container_name: kibana
privileged: true
links:
- elasticsearch:es #可以用es这个域名访问elasticsearch服务
depends_on:
- elasticsearch #kibana在elasticsearch启动之后再启动
environment:
- "elasticsearch.hosts=http://es:9200" #设置访问elasticsearch的地址
ports:
- 45601:5601
五、我该如何持久化
volumes https://docs.docker.com/storage/volumes/
volumes 是用于 docker 做数据存储的首选机制
- 更容易备份或者迁移
- 更适用于 linux 系统
- 可以在多个容器之间更安全的共享
- 不会增加容器的大小,生命周期也在容器外
Try 一下
https://nas.asmrs.xyz:48091/archives/easy-nav
六、拥有自己的镜像
Docker 可以去读来自 Dockerfille 中的组装镜像的命令,可以使用 docker build
来创建一个镜像
FROM registry.cn-shenzhen.aliyuncs.com/ideamakezh/java:8
ENV NACOS_ID 736c6c14-4ab1-436c-a1c3-49955c1a56cd
ENV NACOS_ADDR 47.115.31.214:8848
RUN export NACOS_ID=${NACOS_ID}
RUN export NACOS_ADDR=${NACOS_ADDR}
ARG JAR_FILE
ADD target/${JAR_FILE} /app.jar
CMD ["java", "-jar", "-Dserver.port=9100", "/app.jar"]
FROM
用于初始化一个基础镜像,有效的 Dockerfille 都必须由 FROM
开始。
ARG
变量,使用 docker build
传递
docker build --build-arg JAR_FILE=app.war .
ENV
环境变量,镜像的
EXPOSE
通知 Docker 容器在运行时侦听指定的网络端口。可以指定端口监听 TCP 还是 UDP,如果不指定协议,则默认为 TCP。实际上并未发布端口,具体还是要由运行容器的时候决定。
ADD
往镜像中追加文件
RUN
运行命令
CMD
只能有一个,如果有多个则最后一个才生效。CMD
主要是为了给容器提供默认值或者是入口
更多方式
commit 不建议
docker commit -a "czq" -m "增加一个xxx" CONTAINER_ID NGINX:V1
七、原理解析
Docker 底层是使用 Go 进行编写,利用了 linux 内核的几个特征来为其提供功能。
Namespaces
用于隔离不同的容器的执行空间。Docker 使用 namespaces 的技术来隔离工作空间。当运行容器的时候,docker 会为该容器创建一组独立的命名空间。
- pid 进程号
- net 网络
- ipc 进程通讯
- mnt 文件系统挂载
- uts Unix timesharing system 分时系统 版本 内核 主机名 等
cd /procps
Control groups
用于分配硬件资源。限制一个容器的所能调用的系统资源,将主机性能发挥到极致。
- 内存
- 网络
- cpu
- 文件读写
Union file systems
联合文件系统。通过创建 layer 分层,使得文件系统非常轻量化。
最上面这两层属于容器范畴。这两层分别为Docker容器的初始层(init Layer)与可读写层(Read-write Layer)
初始层大多是与容器相关的一些环境信息,主机名 host 之类的文件
写入层 Docker 容器内的进程只对可读可写层拥有写权限,其它层进程而言都是只读的(Read-Only)。关于 VOLUME 以及容器的 host、hostname 文件都会挂载到这里。
写时复制
表示只是在需要写时才去复制,这个是针对已有文件的修改场景,比如基于一个i mage 启动多个Container ,如果每个 Container 都去分配一个 image 一样的文件系统,那么将会占用大量的磁盘空间。而 CoW 技术可以让所有的容器共享 image 的文件系统,所有数据都从 image 中读取,只有当要对文件进行写操作时,才从 image 里把要写的文件复制到自己的文件系统进行修改。所以无论有多少个容器共享一个 image,所做的写操作都是对从 image 中复制到自己的文件系统的副本上进行,并不会修改 image 的源文件,且多个容器操作同一个文件,会在每个容器的文件系统里生成一个副本,每个容器修改的都是自己的副本,互相隔离,互不影响。使用 CoW 可以有效的提高磁盘的利用率。
Netlink
容器间进程通讯
Linux Bridge
虚拟网桥
Host
container
Docker | Vmware | |
---|---|---|
性能 | 没有损耗 | 有一定的损耗 |
隔离性 | namespace | 很强 |
八、比较有意思的镜像
Emby
导航
Halo
参考资料
Docker 文档 Docker run reference
Docker compose 文档 https://docs.docker.com/compose/reference/
Docker 日志机制 https://nas.asmrs.xyz:48091/archives/dockerlog
Docker 核心技术 http://dockone.io/article/2941