我正在参加「掘金·启航计划」
前端或者后端攻城狮可能听过docker这个神奇的东东 今天来浅浅的进行docker的简单概述
内容提示:基础简介与命令使用
Docker简介
什么是Docker
Docker 使用 Go 语言开发实现 基于Linux 内核的 cgroup namespace 以及 OverlayFS类的UnionFS等技术 对进程进行封装隔离 属于操作系统层面的虚拟化技术
Docker在容器的基础上 进行了进一步封装 传统虚拟机:虚拟出一套硬件 在其上运行一个完整操作系统 容器:容器内应用直接运行与宿主的内核 容器没有自己的内核 没有进行硬件虚拟
为什么要用Docker
- 更高效的利用系统资源
不需要进行硬件虚拟以及运行完整操作系统开销
- 更快速启动
直接运行宿主内核 无需启动完整的操作系统
- 一致的运行环境
Docker 镜像提供了除内核外完整的运行时环境 确保了应用运行环境一致性
- 持续交付和部署
Devops 定制镜像 持续集成 持续部署 使用DockerFile使镜像构建透明化
- 更轻松的迁移
确保了执行环境的一致性 使得应用迁移更容易
- 更轻松的维护和拓展
分层存储 镜像技术 官方镜像 :可以直接在开发模式使用 也可以定制
| 特性 | 容器 | 虚拟机 |
|---|---|---|
| 启动 | 秒级 | 分钟级 |
| 硬盘使用 | 一般为MB | 一般为GB |
| 性能 | 接近原生 | 弱于 |
| 系统支持量 | 单机支持上千容器 | 一般几十个 |
基本概念
镜像 Image
操作系统分为内核和用户空间 Linux内核启动之后会挂在root文件系统为用户空间支持
Docker镜像相当于一个root文件系统 不包含任何动态数据
分层存储
镜像包含操作系统完整的root文件系统 体积是庞大的 利用Union FS 的技术 由一组文件系统组成 一层一层构建 使复用 定制更为容易
容器
面向对象中的类与实例 镜像是静态的定义 容器时镜像运行实体
容器的实质是进程 拥有自己独立的命名空间 文件系统 网络配置 用户id 进程空间都是隔离的
容器存储层的生命周期和容器一样 容器消亡之后 容器存储层随之消亡 任何保存于容器存储层的信息都会随容器删除而丢失
Docker最佳实践:容器存储层要保持无状态化 所有的文件写入操作 应该使用数据卷或者绑定宿主目录
仓库
要在其他服务器上使用镜像 就需要一个集中的存储分发镜像的服务 Dokcer Registry就是这样的服务
包含多个仓库 与标签 一个标签对应一个镜像
通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
Docker Registry 公开服务
官方的 Docker Hub,这也是默认的 Registry,并拥有大量的高质量的 官方镜像。除此以外,还有 Red Hat 的 Quay.io;Google 的 Google Container Registry,Kubernetes 的镜像使用的就是这个服务;代码托管平台 GitHub 推出的 ghcr.io。
私有 Docker Registry
除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务
使用镜像
获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。下载过程中给出了每一层的 ID 的前 12 位。并且下载结束后,给出该镜像完整的 sha256 的摘要,以确保下载一致性。
运行
docker run -it --rm ubuntu:18.04 bash
- -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
- --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
- ubuntu :18.04 :这是指用ubuntu:18.04 镜像为基础来启动容器。
- bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash。
列出镜像
docker image ls
镜像体积
DockerHub显示的是压缩后体积 由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 none 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image) ,可以用下面的命令专门显示这类镜像
# 显示
docker image ls -f dangling = true
# 删除
docker image prune
悬浮镜像
镜像既没有仓库名,也没有标签,均为 none。
中间层镜像
docker image ls -a
只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。
列出部分镜像
docker image ls ubuntu
docker image ls ubuntu:18.04
docker image ls -f since=mongo:3.2
特定格式显示
docker image ls --format "{{.ID}}: {{.Repository}}"
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
删除镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
docker image rm 501
docker image rm centos
docker image ls --digests
docker image rm node@sha256:b4f
Untagged 和 Deleted
当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像
是将满足我们要求的所有镜像标签都取消,这就是我们看到的 Untagged 的信息。
当该镜像所有的标签都被取消了,该镜像很可能会失去了存在的意义,因此会触发删除行为。
用docker image ls 命令来配合
docker image rm $(docker image ls -q redis)
docker image rm $(docker image ls -q -f before=mongo:3.2)
使用Dockerfile定制镜像
镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
FROM指定基础镜像
RUN执行命令
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
# 错误写法 (创建了七层镜像 很多运行时不需要的东西也被装进了镜像)
FROM debian:stretch
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install
# 正确写法
FROM debian:stretch
RUN set -x; buildDeps='gcc libc6-dev make wget' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
docker build 构建镜像
操作容器
启动
启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(exited)的容器重新启动。 因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器。
新建并启动
$ docker run ubuntu:18.04 /bin/echo 'Hello world'
Hello world
//-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,
//-i 则让容器的标准输入保持打开。
$ docker run -t -i ubuntu:18.04 /bin/bash
root@af8bae53bdd3:/#
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从 registry 下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
启动已终止容器
docker container start
守护态运行
docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
docker container ls
docker container logs [container ID or NAMES]
终止
docker container stop
docker container restart
进入容器
//如果从这个 stdin 中 exit,会导致容器的停止。
docker attach 243c
docker exec -i 69d1 bash
ls
bin
boot
dev
...
docker exec -it 69d1 bash
root@69d137adef7a:/#
导出和导入
//导出
docker export 7691a814370e > ubuntu.tar
//导入
cat ubuntu.tar | docker import - test/ubuntu:v1.0
docker import http://example.com/exampleimage.tgz example/imagerepo
删除
//删除处于终止状态的容器
docker container rm
//清理所有处于终止状态的容器
docker container prune
数据管理
介绍如何在Docker内部以及容器之间管理数据 在容器中管理数据主要有两种方式
- 数据卷 Volumes
- 挂载主机目录 Bind mounts
数据卷
数据卷是一个可供一个或多个容器使用的特殊目录
-
数据卷在容器之间共享和重用
-
对数据卷的修改会立马生效
-
对数据卷的更新不会影响镜像
-
数据卷会一直存在即使容器被删除
创建一个数据卷
docker volume create my-vol
docker volume ls
//查看指定数据卷信息
docker volume inspect my-vol
启动一个挂在数据卷的容器
docker run -d -P \
--name web \
# -v my-vol:/usr/share/nginx/html \
--mount source=my-vol,target=/usr/share/nginx/html \
nginx:alpine
查看数据卷具体信息
//查看web容器信息
docker inspect web
删除数据卷
docker volume rm my-vol
挂载主机目录
加载主机的 /src/webapp 目录到容器的 /usr/share/nginx/html目录 Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加 readonly 指定为 只读。
docker run -d -P \
--name web \
# -v /src/webapp:/usr/share/nginx/html \
--mount type=bind,source=/src/webapp,target=/usr/share/nginx/html \
nginx:alpine
使用网络
外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。 当使用 -P 标记时,Docker 会随机映射一个端口到内部容器开放的网络端口。
-p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。
docker run -d -p 80:80 nginx:alpine
docker run -d -p 127.0.0.1:80:80 nginx:alpine
//绑定任意端口 自动分配
docker run -d -p 127.0.0.1::80 nginx:alpine
//udp
docker run -d -p 127.0.0.1:80:80/udp nginx:alpine
查看映射端口配置
docker port
docker port fa 80
0.0.0.0:32768
//绑定多个端口
docker run -d \
-p 80:80 \
-p 443:443 \
nginx:alpine
容器互联
新建网络
docker network create -d bridge my-net
连接容器
docker run -it --rm --name busybox1 --network my-net busybox sh
docker run -it --rm --name busybox2 --network my-net busybox sh
docker container ls
# ping busybox2
PING busybox2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms
Docker Compose
多容器互联 建议使用 Docker Compose
配置DNS
挂载相关文件
Docker Compose
Docker Compose 是 Docker 官方编排项目之一 负责快速的部署分布式应用
简介
Compose 定位是 定义和运行多个Docker容器的应用
使用Dokcerfile模板文件 可以让用户很方便的定义一个单独的容器应用
Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
Compose 重要概念
-
服务 一个运行的容器 实际上可以包括若干运行相同镜像的容器实例
-
项目 由一组关联的应用容器组成的一个完整业务单元 在 docker-compose.yml中定义 Compose默认管理对象是项目 通过子命令对容器中一组容器进行便捷的生命周期管理
使用
DockerFile
FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]
docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
运行
docker-compose up
命令说明
命令选项
- -f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定。
- -p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
- --verbose 输出更多调试信息。
- -v, --version 打印版本并退出。
命令使用说明
docker-compose build [options] [SERVICE...]
构建(重新构建)项目中的服务容器。
config 验证 Compose 文件格式是否正确,若正确则显示配置,若格式错误显示错误原因。
down 此命令将会停止 up 命令所启动的容器,并移除网络
exec 进入指定的容器。
help 获得一个命令的帮助。
images 列出 Compose 文件中包含的镜像。
kill 格式为 docker-compose kill [options] [SERVICE...]。
通过发送 SIGKILL 信号来强制停止服务容器。 支持通过 -s 参数来指定发送的信号,例如通过如下指令发送 SIGINT 信号。
$ docker-compose kill -s SIGINT
logs 格式为 docker-compose logs [options] [SERVICE...]。 查看服务容器的输出。默认情况下,docker-compose 将对不同的服务输出使用不同的颜色来区分。可以通过 --no-color 来关闭颜色。 该命令在调试问题的时候十分有用。
pause 暂停
port 打印端口
ps 列出容器
pull/push 拉取/推送 镜像
restart 重启服务
rm 删除
run 执行命令
up 尝试自动完成包括构建镜像 重写创建服务 启动服务 关联服务相关容器的一系列操作
- -d 在后台运行服务容器。
- --no-color 不使用颜色来区分不同的服务的控制台输出。
- --no-deps 不启动服务所链接的容器。
- --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用。
- --no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用。
- --no-build 不自动构建缺失的服务镜像。
- -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。
Compose模板文件
默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式
version: "3"
services:
webapp:
image: examples/web
ports:
- "80:80"
volumes:
- "/data"
build 指定路径
devices 指定设备映射关系
depends_on 解决依赖关系
expose 暴露端口 植不映射到宿主机 只被连接服务访问
ports 暴露端口信息
secrets 存储敏感信息
volumes 数据卷挂载地址
结语
docker作为目前云原生火热的产品 为微服务部署开发带来了便利
基于虚拟化的云原生技术正在大放异彩 docker 我学定了!