docker

概述:docker

docker

Docker官方文档

Docker从入门到实践

1.docker&VM

传统虚拟化

img

Docker

img

docker 架构

![image-20210126190803002](/Users/junmingguo/Library/Application Support/typora-user-images/image-20210126190803002.png)

docker镜像由文件+元数据组成,元数据包括:环境变量、端口映射、卷等其它细节

Container = cgroup + namespace + rootfs + Container Engine

cgroup即ControlGroup,LInux操作系统通过cgroup设置进程使用CPU 内存 IO资源的限额

docker运行命令配置:–cpu-shares, –memory, –device-write-bps实际在配置cgroup

namespace实现了容器间资源的隔离,Linux使用了六种namespace,分别是:

  1. Mount

  2. UTS namespace

  3. IPC namespace

  4. PID namespace

  5. Network namespace

  6. User namespace

2.基本概念

2.1 镜像

Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。

2.2 容器

容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

2.3 仓库

一个 Docker Registry 中可以包含多个 仓库Repository);每个仓库可以包含多个 标签Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

3.目标及使用场景

3.1 目标

提供简单轻量的建模方式

职责的逻辑分离

快速高效的开发生命周期

鼓励使用面向服务的架构

3.2 使用场景

(1)使用docker容器开发、测试、部署服务

(2)创建隔离的运行环境

(3)搭建测试环境

(4)构建多用户的平台即服务(PaaS)基础设施

(5)提供软件即服务(SaaS)应用程序

(6)高性能、超大规模的宿主机部署

3.3 能力

(1)文件系统隔离:每一个容器都有自己的root文件系统

(2)进程隔离:每一个容器都运行在自己的进程环境中

(3)网络隔离:容器间的虚拟网络接口和IP地址是分开的

(4)资源隔离和分组:使用cgroup将cpu和内存之类的资源独立分配给每一个docker容器

4.常见命令

1.基础

1.1 安装docker(mac OS)

1
brew cask install docker

1.2 查看docker版本

1
2
3
4
5
6
docker --version
# Docker version 19.03.8, build afacb8b
docker-compose --version
# docker-compose version 1.25.5, build 8a1c60f6
docker-machine --version
# docker-machine version 0.16.1, build cce350d7

1.3 测试docker是否成功安装

1
2
docker run hello-world
# 首先会显示无法在本地寻找到`hello-world`镜像,之后会进行拉取

1.5 登录远程 login

1
2
3
# docker login -u <用户名> -p <密码> <URL>
docker login -u username -p password registry
# docker login -u junmingguo -p guojunming123 csighub.tencentyun.com

1.6 查看容器网络列表 ls

1
2
3
4
docker network ls
--network=host 指定使用host网络

ifconfig docker0 查看网络

—————————

2. 容器

2.1 进入容器 exec

1
2
3
4
5
6
7
8
docker exec -it CONTAINER_ID/NAME bash
# 若修改了容器文件,可使用docker differ webserver 查看改动内容

# or docker attach CONTAINER_ID (不方便,当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。)

# 退出
# exit 关闭容器并退出
# ctrl + q + p 不关闭容器,重新定位到本地目录

2.2 查看容器 ps

1
2
3
4
5
6
7
8
# 查看正在运行的容器
docker ps

# 查看所有的容器
docker ps -a

# 查看容器访问日志
docker logs CONTAINER_ID

2.3 删除容器 rm

1
2
docker rm CONTAINER_ID
docker container prune # 清除所有处于终止状态的容器

2.4 运行容器 run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
docker run -it python

-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
-i 则让容器的标准输入保持打开
-d 在后台开启进程

eg. docker run
-itd
-p 8082:8082
-v /Users/sam/Desktop/service-a.jar:/usr/service-a.jar
--name service-a
d23bdf5b1b1b java -jar /usr/service-a.jar

-p 8082:8082配置映射端口 分别表示=>我的端口:虚拟机端口 即把虚拟机中的8082端口映射到我的电脑上的8082上

-v /Users/sam/Desktop/service-a.jar:/usr/service-a.jar 表示将jar文件挂载到虚拟机目录,冒号前后分别是自己的jar文件路径和挂载到虚拟机中的路径【如果docker images 存在镜像则无需挂载】


--name service-a 定义容器名称 service-a
d23bdf5b1b1b java -jar /usr/service-a.jar d23bdf5b1b1b 是java镜像的ID号;java -jar /usr/service-a.jar 运行jar文件的命令(因为jar文件中包含tomcat所以直接运行就可以开启你的微服务)


-i, --interactive Keep STDIN open even if not attached
-t, --tty Allocate a pseudo-TTY
-d, --detach Run container in background and print container ID

守护态运行容器:让 Docker 容器在后台以守护态(Daemonized)形式运行

1
2
3
4
5
6
docker run -d ubuntu:18.04 
# -d 会将容器的输出结果保存,而不是直接输出至终端,会返回一串id

docker container ls # 查看容器列表

docker container logs <CONTAINER_ID or CONTAIN_NAME> # 查看容器输出信息

容器对资源的使用限制

1
2
3
4
5
6
docker run -d -it -c 1024 --memory 200M --memory-swap 300M --blkio-weight 600 ubuntu bash
-m,--memory 内存使用限额
--memory-swap 设置内存+swap使用限额
-c,--cpu-shares CPU限制权重值,默认1024
--blkio-weight 容器可平等读写硬盘
--device-read-bps 限制设备bps

2.5 启动和终止容器 start/stop

启动时针对已经终止的容器启动运行

1
2
3
4
docker container start
docker container stop # 终止一个运行中的容器
docker container restart
docker container ls -a # 可查看到终止状态的容器

2.6 重新启动/停止容器

1
2
docker start CONTAINER-ID
docker stop CONTAINER-ID

2.7 导出容器 export

导出容器快照到本地文件

1
docker export 7691a814370e > ubuntu.tar

2.8 导入容器 import

1
docker import - test/ubuntu:v1.0

—————————

3. 镜像

3.1 拉取镜像 pull

从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub(docker.io)。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

比如:

1
docker pull ubuntu:18.04

从Docker Hub拉取镜像

1
2
docker search centos  # 搜索centos相关的镜像
docker pull centos # 拉取centos镜像

3.2 运行指定镜像 run

1
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

启动容器并运行nginx

1
2
3
4
5
6
docker run --name webserver -d -p 80:80 nginx
# webserver 容器名称
# -d: 后台运行容器,并返回容器ID
# -p: 指定端口映射:格式本地 80 端口 映射到容器的 80 端口
# -p 127.0.0.1::80 则本地任意端口,本地会自动分配一个端口
# 访问http://localhost即可

启动定制的镜像

1
2
3
4
5
6
docker run --name mywebserver -d -p 81:80 nginx:v2
# 映射到81端口
# ================================================
docker run -t -i ubuntu:18.04
# -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
# -i 让容器的标准输入保持打开

3.3 查看本地镜像列表 images

1
2
docker image ls [CONTAINER_NAME]
# 或者 docker images

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

其中镜像ID是镜像的唯一标识,而一个镜像可以对应多个标签,其中你可能发现存在的仓库名,如下图所示:

![image-20201021195826724](/Users/junmingguo/Library/Application Support/typora-user-images/image-20201021195826724.png)

镜像称为无标签镜像,也称为虚悬镜像(dangling image)

查看虚悬镜像

1
docker image ls -f dangling=true

删除虚悬镜像

1
docker image prune

查看镜像、容器、数据卷所占用的空间

1
docker system df

3.4 删除本地镜像 rmi

1
2
3
4
5
docker image rm IMAGE_ID
docker rmi IMAGE_ID

# 强制删除镜像
docker rmi -f IMAGE_ID

若镜像所在的容器正在运行,会出现删除镜像失败的情况。

批量删除镜像 -> 包含none文字的所有镜像

1
docker rmi $(docker images | grep "none" | awk '{print $3}') 

3.5 保存容器成镜像 commit

1
2
3
4
5
6
7
# docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
eg.
docker commit --author "junming" --message "update something" webserver nginx:v2

docker commit b72ad733f605 java/service-a
# b72ad733f605 容器ID
# java/service-a 镜像名称

3.6 创建镜像 build

使用Dockerfile创建镜像,其中Dockerfile示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
FROM python:3.7

ENV TZ=PRC

# 镜像源设置,一般不会有修改
COPY docker/pip.conf /etc/
COPY docker/sources.list /etc/apt/

# 复制 vim 安装脚本
COPY docker/install_vim.sh /usr/local/bin/

# supervisor 配置
COPY docker/supervisord.*.conf /etc/

# 复制并安装项目依赖
COPY requirements.txt /app/
RUN pip3 install --use-feature=2020-resolver -r /app/requirements.txt supervisor uwsgi

# 复制项目文件
COPY . /app/
WORKDIR /app

# 收集静态文件
RUN python3 manage.py collectstatic --noinput

# 删除所有临时文件,减少镜像大小
RUN rm -rf /tmp/*

EXPOSE 80

将Dockerfile打包成tar

1
2
3
4
5
6
7
8
docker build . -f Dockerfile -t IMAGE_NAME --network host

# docker build [选项] <上下文路径/URL>
eg.
docker build -f Dockerfile -t abc.com/cd/scheduler:TAG1 --network host
# -f 指定Dockfile文件
# -t 上下文路径/URL
# --network 在构建期间设置RUN指令的网络模式

3.7 推送镜像至指定位置 push

1
docker push URL+路径:tag

3.8 镜像重命名 tag

1
docker tag IMAGE_ID IMAGE_NAME

3.9 保存镜像 save

1
2
3
# 将镜像导出为tar文件
docker save -o IMAGE_NAME IMAGE_ID
eg.docker save -o ubuntu_14.04.tar ubuntu:14.04

3.13 载入镜像 load

1
2
3
# 导入自定义镜像
docker load -i TAR_FILE
eg.docker load --input ubuntu_14.04.tar

—————————

4. 数据卷

数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 卷会一直存在,直到没有容器使用

*数据卷的使用,类似于 Linux 下对目录或文件进行 mount。

4.1 创建数据卷

在用 docker run 命令的时候,使用 -v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。

下面创建一个 web 容器,并加载一个数据卷到容器的 /webapp 目录。

1
docker run -d -P --name web -v /webapp training/webapp python app.py

4.2 挂载一个本地主机文件作为数据卷

-v 标记也可以从主机挂载单个文件到容器中

1
$ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

4.3 数据卷容器

如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。

数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。

创建一个命名的数据卷容器 dbdata:

1
docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

其他容器中使用 --volumes-from 来挂载 dbdata 容器中的数据卷。

1
docker run -d --volumes-from dbdata --name db1 training/postgres

可以使用多个 --volumes-from 参数来从多个容器挂载多个数据卷

注意:使用 --volumes-from 参数所挂载数据卷的容器自己并不需要保持在运行状态。

4.4 利用数据卷容器来备份、恢复、迁移数据卷

备份

首先使用 --volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:

1
docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

容器启动后,使用了 tar 命令来将 dbdata 卷备份为本地的 /backup/backup.tar

恢复

如果要恢复数据到一个容器,首先创建一个带有数据卷的容器 dbdata2。

1
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然后创建另一个容器,挂载 dbdata2 的容器,并使用 untar 解压备份文件到挂载的容器卷中。

1
2
docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf
/backup/backup.tar

—————————

5.网络

5.1外部访问容器

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P-p 参数来指定端口映射。

当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。

使用 docker ps 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。此时访问本机的 49155 端口即可访问容器内 web 应用提供的界面。

eg.

1
docker run -d -P training/webapp python app.py

-p(小写的)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有```

1
ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort

5.2 映射所有接口地址

使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行

1
$ sudo docker run -d -p 5000:5000 training/webapp python app.py

此时默认会绑定本地所有接口上的所有地址。

5.3 映射到指定地址的指定端口

可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1

1
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

5.4 映射到指定地址的任意端口

使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。

1
$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py

还可以使用 udp 标记来指定 udp 端口

1
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

5.5 查看映射端口配置

使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址

1
2
$ docker port nostalgic_morse 5000
127.0.0.1:49155.

注意:

  • 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)
  • -p 标记可以多次使用来绑定多个端口

例如

1
$ sudo docker run -d -p 5000:5000  -p 3000:80 training/webapp python app.py

5.6 容器互联

容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式。

该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。

🔗链接:http://www.dockerinfo.net/%e4%bd%bf%e7%94%a8%e7%bd%91%e7%bb%9c