Docker入门

容器技术介绍

原始方式的应用程序部署有以下不足:

  1. 部署非常慢(需要找机房,安装操作系统及各种环境等)

  2. 成本非常高(有些应用程序占用的资源非常少,但是我们还是要部署一个机器,成本很高)

  3. 资源浪费(应用程序使用资源很少,导致我们的机器很多资源都在空置,造成浪费)

  4. 难于迁移和扩展(我们迁移应用的时候需要重新找机器安装各种环境,扩展同理,也需要我们准备各种环境,有的时候可以通过扩展机器配置来完成,但这样也很麻烦)

虚拟化技术出现以后:

一个物理机可以部署多个APP,每个APP可以运行在单独的一个VM中,虚拟化的优点:

  1. 资源池:一个物理机的资源分配到了不同的虚拟机中,可以节约资源

  2. 很容易扩展:在扩展的时候我们可以通过添加物理机或加虚拟机的方式来实现

虚拟化的局限性:

每个虚拟机都是一个完整的操作系统,需要给其分配资源,当虚拟机数量增多时,操作系统本身消耗的资源势必增多

容器技术解决了什么问题:

  1. 对软件和其依赖的标准化自动化打包和发布

  2. 能实现应用之间的相互隔离,类似于上述虚拟化技术的隔离,但是它的隔离没有虚拟化技术隔离的那么好

  3. 容器可以共享同一个OS(实现多个应用程序运行在一个OS上)

  4. 可以运行在很多主流的操作系统上

容器是APP层面的隔离,虚拟化是物理资源层面的隔离,我们也可以将虚拟化技术与容器技术结合使用,既对物理机器划分为不同的VM,每个VM上运行多个容器

Docker介绍

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker的优点

Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。

1、快速,一致地交付您的应用程序

Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。

容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:

您的开发人员在本地编写代码,并使用 Docker 容器与同事共享他们的工作。
他们使用 Docker 将其应用程序推送到测试环境中,并执行自动或手动测试。
当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中,以进行测试和验证。
测试完成后,将修补程序推送给生产环境,就像将更新的镜像推送到生产环境一样简单。

2、响应式部署和扩展

Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 容器可以在开发人员的本机上,数据中心的物理或虚拟机上,云服务上或混合环境中运行。

Docker 的可移植性和轻量级的特性,还可以使您轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。

3、在同一硬件上运行更多工作负载

Docker 轻巧快速。它为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案,因此您可以利用更多的计算能力来实现业务目标。Docker 非常适合于高密度环境以及中小型部署,而您可以用更少的资源做更多的事情。

Docker架构和底层技术实现

docker的前生LXC

LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpace。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。与传统虚拟化技术相比,它的优势在于:

  1. 与宿主机使用同一个内核,性能损耗小;

  2. 不需要指令级模拟;

  3. 不需要即时(Just-in-time)编译;

  4. 容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;

  5. 避免了准虚拟化和系统调用替换中的复杂性;

  6. 轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享。

总结:Linux Container是一种轻量级的虚拟化的手段。Linux Container提供了在单一可控主机节点上支持多个相互隔离的server container同时执行的机制。Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源的虚拟化。

docker并不是LXC替代品,docker底层使用了LXC来实现,LXC将linux进程沙盒化,使得进程之间相互隔离,并且能够控制各进程的资源分配。

Docker架构

Docker架构可以分为三个部分

  1. Docker Client:这个就是我们平时操作Docker的主要入口,我们输入各种命令都是通过Client来操作的,客户端可以与Docker在同一个服务

  2. Docker Host:是我们启动了docker的机器,也就是Docker所在的服务器,这上面主要有两个重要的概念,Containers(镜像)和images(容器)

  • Image镜像:docker镜像就是一个只读模板,比如,一个镜像可以包含一个完整的centos,里面仅安装apache或用户的其他应用,镜像可以用来创建docker容器,另外docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

  • Image是文件和meta data的集合,Linux分为内核空间和用户空间,内核空间就是Linux Kernel,也称为bootfs,用户空间其实就是基于此内核空间我们创建了各种Linux的发行版本,比如Ubuntu,CentOS,Debian等,这些其实就是一个Image,被称为Base Image,在此基础上,我们可以创建更高一级的Image,Base Image是不包含Liunx内核的,所以我们这些不同的Image可以共享Linux内核,也就是bootfs。我们可以在此Base Image上安装各种不同的软件,然后就形成了新的Image,个人理解Image就是基于内核安装各种不同的软件,然后形成不同的镜像,成为Image。所以Image是可以分层的,我们可以在每一层添加和删除文件,形成新的Image。

  • Image的获取有两种方式,1.我们的Docker Image,可以通过手动创建Dockerfile,然后根据它的语法来写入指令,实现自己的Dockerfile。2.Pull from Registry,其实就是类似于GitHub,我们通过Pull命令来此远程仓库拉取公开的各种Dockerfile,一般是通过Docker Hub来拉取,它是一个官方的仓库,我们可以去此仓库找到我们需要的Dockerfile,下载到本地,来创建我们的专用的Docker容器。

  • container容器:docker利用容器来运行应用,容器是从镜像创建的运行实例,它可以被启动,开始、停止、删除、每个容器都是互相隔离的,保证安全的平台,可以把容器看做是要给简易版的linux环境(包括root用户权限、镜像空间、用户空间和网络空间等)和运行再其中的应用程序。

  • container是通过image创建的。container是在image之上建立的一个container layer(可读写),image是一个只读的东西,container要去运行程序或者安装软件,所以它是可写的。container和image类似与我们Java中类和实例的关系,container就是实例,image是负责app的存储和分发的,Container负责运行App。

  1. Registry:是一个存储容器镜像的仓库。而容器镜像是在容器被创建时,被加载用来初始化容器的文件架构与目录。它可以理解为我们的GitHUb,仓库是集中存储镜像文件的,registry是仓库主从服务器,实际上参考注册服务器上存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag),仓库分为两种,公有参考,和私有仓库,最大的公开仓库是docker Hub,存放了数量庞大的镜像供用户下周,国内的docker pool,这里仓库的概念与Git类似,registry可以理解为github这样的托管服务

底层技术支持

  • Namespace

docker是通过namespace实现资源隔离,它可以实现六项资源的隔离,

  1. UTS:主机与域名

  2. IPS:信号量和消息队列和共享内容

  3. PID:进程编号

  4. NETWORK:网络设备、网络栈、端口等

  5. MOUNT:挂载点,既文件系统

  6. USER:用户和用户组

  • Control Group

CGroup它是用来做资源限制的,主要有四大功能:

  1. 资源限制:可以对任务使用的资源总额进行限制

  2. 优先级分配:通过分配的cpu时间片数量以及磁盘IO带宽大小,实际上相当于控制了任务运行优先级

  3. 资源统计:可以统计系统的资源使用量,如cpu时长,内存用量等

  4. 任务控制:cgroup可以对任务执行挂起、恢复等操作

  • Union file systems

Container和image的分层,Docker的存储驱动的实现是基于Union File System,简称UnionFS,他是一种为Linux 、FreeBSD 和NetBSD 操作系统设计的,把其他文件系统联合到一个联合挂载点的文件系统服务。它用到了一个重要的资源管理技术,叫写时复制。写时复制(copy-on-write),也叫隐式共享,是一种对可修改资源实现高效复制的资源管理技术。对于一个重复资源,若不修改,则无需立刻创建一个新的资源,该资源可以被共享使用。当发生修改的时候,才会创建新资源。这会大大减少对于未修改资源复制的消耗。Docker正式基于此去创建images和containers

入门使用及基本命令

Image操作

  1. 查询当前所有的image:docker image ls 或者 docker images

  2. 删除image:docker image rm ‘Image ID’ 或者 docker rmi ‘Image ID’, ‘Image ID‘是通过ls命令查出的,有时候我们一个Dockerfile被build成了多个image,这时我们不能直接删除,可以加 -f 参数来强制删除,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1.查看所有的image
jw@jjw-PC:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
jjw-story/hello-docker-c latest 73404f3002a9 47 minutes ago 756kB
jjw-story/hello-docker-copy latest f982998b02d3 49 minutes ago 682B
jjw-story/hello-docker latest ad1e583a2447 51 minutes ago 682B

# 第一种删除方案
# 2.删除失败
jjw@jjw-PC:~$ docker image rm f982998b02d3
Error response from daemon: conflict: unable to delete f982998b02d3 (must be forced) - image is being used by stopped container 88443ef588b1

# 3.强制删除
jjw@jjw-PC:~$ docker image rm -f f982998b02d3
Untagged: jjw-story/hello-docker-copy:latest
Deleted: sha256:f982998b02d382876511b156632c77d795a8155103e4a7e2c4d67703a16be89c

# 4.查看结果
jjw@jjw-PC:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jjw-story/hello-docker-c latest 73404f3002a9 About an hour ago 756kB
jjw-story/hello-docker latest ad1e583a2447 About an hour ago 682B

如上示例,COMMAND 列展示的其实是我们在 Dockerfile CMD项 指定的命令

Container操作

  1. 创建container即实例化Image:docker run ‘Image tag’,image tag就是我们使用Dockerfile构建image时指定的tag

  2. 交互式运行container,及后台运行不自动关闭,以便我们可以再次container中进行一些操作:docker run -it ‘Image name’,如下示例:

1
2
jjw@jjw-PC:~$ docker run -it jjw-story/hello-docker-c
hello docker
  1. 后台运行container:docker run -d ‘Image name’

  2. 查看当前所有正在运行的container:docker container ls,如下示例:

  3. 查看所有的container,包括历史运行的:docker container ls -a 或者 docker ps -a,如下示例:

1
2
3
4
jjw@jjw-PC:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
979454ee2253 jjw-story/hello-docker-c "/hello" 4 minutes ago Exited (0) 4 minutes ago sweet_davinci
ad4051fc47ed jjw-story/hello-docker "java /HelloWorld" 4 minutes ago Created clever_goodall

上述查询结果中,COMMAND 展示的就是我们在编写Dockerfile时制定的 CMD 所对应的命令内容

  1. 删除container: docker container rm ‘Container ID’ 或者直接 docker rm ‘Container ID’ 效果是一样的,默认删除的就是container,Container ID是通用 container ls 命令查询出来的,这里的ID我们也可以只写ID的前几位,只要能区分出唯一即可,例如:
1
2
3
4
5
6
7
8
9
10
jw@jjw-PC:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4d452d8cf2c jjw-story/hello-docker-c "/hello" 3 minutes ago Exited (0) 3 minutes ago competent_varahamihira
6f40251fb684 jjw-story/hello-docker-c "/hello" 4 minutes ago Exited (0) 4 minutes ago jovial_keldysh

jw@jjw-PC:~$ docker container rm 6f
6f
jjw@jjw-PC:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4d452d8cf2c jjw-story/hello-docker-c "/hello" 5 minutes ago Exited (0) 5 minutes ago competent_varahamihira
  1. 查看当前所有的container,并只显示id:docker container ls -aq,此命令会显示标题。去除标题:docker container ls -a | awk {‘print$1’}

  2. 基于上述命令删除所有的container:docker rm $(docker container ls -aq)

  3. 查看所有已经退出的容器:docker container ls -f “status=exited”, 只列出ID:docker container ls -f “status=exited” -q

  4. 删除所有已退出的容器:docker rm $(docker container ls -f “status=exited” -q)

最后更新: 2020年05月07日 09:51

原始链接: https://jjw-story.github.io/2020/04/20/Docker入门/

× 请我吃糖~
打赏二维码