1.Docker简介

1.1 题外话–运输业货运方式

集装箱▼
在这里插入图片描述
集装箱被发明之前▼
在这里插入图片描述

两种货运方式的对比:

散货运输 集装箱运输
货物装载时间 几天到一个星期,分拣、合并、装卸过程繁琐 几个小时
货物装卸时间占整个运输过程的比例 > 50% < 10%
所需劳动力 大量码头工人 少数码头工人和起重机操作员
自动化程度
安全性
总体运输时间 货物装卸时间+实际运输时间 在总距离和运输工具的运输速度不变的前提下,可以节约一半以上的时间

1.2 什么是Docker

在这里插入图片描述

Docker['dɑkɚ]: 码头工人

Docker 是一种容器(Container)技术,它可以将应用和环境等进行打包,形成一个独立的,类似于 iOS/Android 的 APP 形式的「应用」,这个应用可以直接被分发到任意一个支持 Docker 的环境中,通过简单的命令即可启动运行。Docker 是一种最流行的容器化实现方案。和虚拟化技术类似,它极大的方便了应用服务的部署;又与虚拟化技术不同,它以一种更轻量的方式实现了应用服务的打包。使用 Docker 可以让每个应用彼此相互隔离,在同一台机器上同时运行多个应用,不过他们彼此之间共享同一个操作系统。Docker 的优势在于,它可以在更细的粒度上进行资源的管理,也比虚拟化技术更加节约资源。
Docker和虚拟化技术的对比
Docker和虚拟化技术的对比▲

结合前面的集装箱技术可以更好的理解docker:

  • 资源独立、隔离
    Docker Engine限制了硬件资源与软件运行环境,与宿主机上的其他应用实现了隔离,做到了互不影响。不同应用或服务以「集装箱」(container)为单位装「船」或卸「船」,「集装箱船」(运行 container 的宿主机或集群)上,数千数万个「集装箱」排列整齐,不同公司、不同种类的「货物」(运行应用所需的程序、组件、运行环境、依赖)保持独立。

  • 环境的一致性
    开发工程师完成应用开发后 build 一个 Docker image,基于这个 image 创建的 container 像是一个集装箱,里面打包了各种「散件货物」(运行应用所需的程序、组件、运行环境、依赖)。无论这个集装箱在哪里——开发环境、测试环境、生产环境,都可以确保集装箱里面的「货物」种类与个数完全相同,软件包不会在测试环境缺失,环境变量不会在生产环境忘记配置,开发环境与生产环境不会因为安装了不同版本的依赖导致应用运行异常。这样的一致性得益于「发货」(build Docker image)时已经密封到「集装箱」中,而每一个环节都是在运输这个完整的、不需要拆分合并的「集装箱」。

  • 轻量化
    相比传统的虚拟化技术(VM),使用 Docker 在 CPU、Memory、Disk I/O、Network I/O 上的性能损耗都有同样水平甚至更优的表现。Container 的快速创建、启动、销毁受到很多赞誉

  • Build Once, Run Everywhere
    「货物」(应用)在「汽车」、「火车」、「轮船」(私有云、公有云等服务)之间迁移交换时,只需要迁移符合标准规格和装卸方式的「集装箱」(Docker container),削减了耗时费力的人工「装卸」(上线、下线应用),带来的是巨大的时间人力成本节约。这使未来仅有少数几个运维人员运维超大规模装载线上应用的容器集群成本可能

2. 开始

2.1 基本概念

  • 镜像(Image):可以理解为一个预配置的系统光盘,这个光盘插入电脑后就可以启动一个操作系统。当然由于是光盘,所以你无法修改它或者保存数据,每次重启都是一个原样全新的系统.
  • 容器(Container):同样一个镜像,我们可以同时启动运行多个,运行期间的产生的这个实例就是容器。把容器内的操作和启动它的镜像进行合并,就可以产生一个新的镜像。

2.2 安装Docker

以Ubuntu系统为例:

  • 使用官方命令安装:
    wget -qO- https://get.docker.com/ | sh

  • 使用国内镜像安装
    curl -sSL https://get.daocloud.io/docker | sh

  • 安装镜像加速器:
    curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

2.3 镜像(Image)操作

  • 搜索镜像
    docker search <image_name>
    如:docker search ubuntu
  • 拉取(下载)镜像
    docker pull <user_name:image_name>:<tag>
    如docker pull name/ubuntu;docker pull name/ubuntu:18.04
  • 查看已拉取的镜像
    docker images
  • 删除镜像(需先删除对应的Container)
    docker rmi <image_id>

2.4 容器(Container)操作

2.4.1 基本操作

操作 命令 说明
启动(创建)一个容器 docker run -it <image_id/image_name> /bin/bash -i表示: 表示这是一个交互容器,会把当前标准输入重定向到容器的标准输入中.
-t表示:为这个容器分配一个终端。也可以仅仅启动容器,不需要交互(前提是你的镜像中要有可执行的前台程序,否则就会立即退出。如果使用我们自己编译好的dotnet项目镜像,因为已经包含有ENTRYPOINT或CMD,就不会自动退出
启动(创建)一个容器2 docker run -d -p 9200:9200 -p 9300:9300 -e "key=value" -e key2="value2" <image_id/image_name> -p:进行端口映射。
-e:设置环境变量。
-d:后台启动
查看所有容器 docker ps -a (docker ps查看正在运行的容器)
查看容器详细信息 docker inspect <container_id>
停止\启动\重启容器 docker start/stop/restart <container_id>
开机自启动容器 docker update --restart always <container_id> 除了aways还可以设置为:no(默认不自动重启),always(总是自动重启,包括开机后),unless-stopped(类似always,但手动stop后重启机器后不会自动启动),on-failure(仅在非正常退出时重启)
连接到容器 docker attach --sig-proxy=false <container_id> 能够连接的前提是容器正在start,–sig-proxy=false确保CTRL-D或CTRL-C不会关闭容器
连接到容器2 docker exec -it <container_id> /bin/bash attach命令无法给容器传入参数进行交互,如果有交互需求可以使用exec命令替代
获取容器的日志 docker logs <container_id> 1. 查看实时日志 docker logs -f <container_id>
2. 查看最近N行日志 docker logs --tail N <container_id>
3.查看某日志后的日志 docker logs --since YYY-MM-DDTHH:MM:SS <container_id>
列出指定的容器的端口映射 docker port <container_id>
删除容器 docker rm <container_id> docker rm $(docker ps -a -f status=exited -q)删除所有exit状态的容器

2.4.2 端口映射

容器启动之前可以通过以下命令进行映射:

docker run -P 80 -it  ubuntu /bin/bash (将容器的80端口映射到主机的任意端口上)
docker run -P 192.168.0.100::80 -it ubuntu /bin/bash (将容器的80端口和192.168.0.100IP,映射到主机的任意端口上)
docker run -p 8000:80 -it ubuntu /bin/bash  (将容器的80端口映射到主机的8000端口上)
docker run -p 192.168.0.100:8000:80 -it ubuntu /bin/bash  (将容器的80端口和192.168.0.100IP,映射到主机的8000端口上)

注意:P和p区别就是是否要映射到注意的任意端口

容器启动之后可以通过以下命令进行映射:

iptables -t nat -A DOCKERTEST  -p tcp -m tcp --dport 8000 -j DNAT --to-destination  192.168.42.2:6379

(将主机的8000端口映射到192.168.42.2容器的6379端口上)

注意:此方式映射之后,无法通过 docker port命令查看映射的端口,可以使用
iptables -t nat -nvL | grep 192.168.42.2 来查看

3.创建/发布镜像

要创建一个新的 Docker 镜像,通常基于一个已有的 Docker 镜像来创建。Docker 提供了两种方式来创建镜像:把容器创建为一个新的镜像、使用 Dockerfile 创建镜像。下面以创建一个包含.netcore sdk的镜像为例, 来演示两种不同的创建方式:

3.1 基于容器创建

docker run -it ubuntu /bin/bash
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-2.1

然后输入以下命令进行创建
docker commit <container_id> <user_name/image_name>
如: docker commit 51f guyiming/firstimage (注意用户名里不能有特殊符号,用户名非必选)

3.2 使用Dockfile创建

使用命令行的方式创建 Docker 镜像通常难以自动化操作。更多的是使用Dockerfile 来创建 Docker 镜像。Dockerfile 是一个纯文本文件,它记载了从一个镜像创建另一个新镜像的步骤。撰写好 Dockerfile 文件之后,我们就可以轻而易举的使用 docker build 命令来创建镜像了。

Dockerfile常见命令:

命令 参数 说明
# - 注释
FROM < image>[:< tag>] 从一个已有镜像创建,例如ubuntu:latest
MAINTAINER Author some-one@example.com 镜像作者名字,如Max Liu some-one@example.com
RUN < cmd>或者[‘cmd1’, ‘cmd2’…] 在镜像创建用的临时容器里执行单行命令
ADD < src> < dest> 将本地的< src>添加到镜像容器中的< dest>位置
RUN < cmd>或者[‘cmd1’, ‘cmd2’…] 在镜像创建用的临时容器里执行单行命令
VOLUME < path>或者[‘/var’, ‘home’] 将指定的路径挂载为数据卷
EXPOSE < port> [< port>…] 将指定的端口暴露给主机
ENV < key> < value> 或者 < key> = < value> 指定环境变量值
CMD [“executable”,“param1”,“param2”] 容器启动时默认执行的命令。注意一个Dockerfile中只有最后一个CMD生效
ENTRYPOINT [“executable”, “param1”, “param2”] 容器的入口点

CMD 和 ENTRYPOINT 需要特殊说明一下:

  • CMD 用来指定 Docker 容器启动时默认的命令,例如我们上面例子提到的 docker run -it ubuntu /bin/bash 。其中 /bin/bash 就是通过手工指定传入的 CMD(覆盖容器内原有的CMD命令进行执行)。如果我们不加这个参数,那么容器将会默认使用 CMD 指定的命令启动,如果构建容器时没有设置CMD,则不会启动。

  • ENTRYPOINT 从字面看是入口点。构建dockerfile时ENTRYPOINT 用来指定特定的可执行文件、Shell 脚本,并把启动参数或 CMD 指定的默认值,作为附加参数传递给 ENTRYPOINT,即对容器所有的操作只能在这个范围内。docker run -it ubuntu xxx时,xxx将被作为参数传给ENTRYPOINT。

论docker中 CMD 与 ENTRYPOINT 的区别

安装.netcore sdk的Dockfile:

FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install wget -y
RUN wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get install apt-transport-https -y
RUN apt-get update
RUN apt-get install dotnet-sdk-2.1 -y

然后输入一下命令进行创建(注意最后的小数点)

docker build -t <user_name/image_name> .

3.3 发布到仓库

创建完成之后使用push命令进行发布.

在发布之前, 需要先登录到dockerhub: docker login -u <user_name>或者登陆到私有仓库docker login www.xxx.com -u username -p password

  1. 如果是push到私有仓库,需要先对构建之后的镜像打tag,如:
    docker tag <imageid> www.xxx.com/seatest_base/dotnetsdk:3.1
    网址就是私有仓库的地址,中间的seatest_base是你私有仓库里项目的名称,最后的dotnetsdk:3.1就是镜像名称和镜像tag了。
  2. tag打好之后push到仓库,
    docker push www.xxx.com/seatest_base/dotnetsdk:3.1

3.4 镜像导入与导出

docker 镜像导入导出有两种方法:

  1. 使用 save 和 load 命令,保存的是一个镜像而非容器。不能对load的镜像重命名。
    docker save -o test.tar <imageid>
    docker load -i test.tar
  2. 使用 export 和 import 命令,导出的是一个容器的快照, 不是镜像本身, 也就是说没有 layer。你的 dockerfile 里的 workdir, entrypoint 之类的所有东西都会丢失,commit 过的话也会丢失。可以为镜像指定新名称。
    docker export -o test.tar <containerid>
    docker import test.tar newgroup/newname:1

需要注意两种方法不可混用。

4. Docker与CI/CD

daocloud为例
tbd

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐