Docker入门

Posted by Chase Shen on 2021-09-07
Estimated Reading Time 9 Minutes
Words 2.8k In Total
Viewed Times

写在前面

 在进行后端开发之前,首先需要在本地搭建一套PHP环境,需要安装PHP、PHP-FPM、WEB服务器、MySQL,有时候还需要Redis和Memcached等NoSQL服务。每个服务又有很多版本,有时候后端开发人员在自己本地安装的版本和运维部署到服务器上的版本会不一样,这样会造成代码不兼容的问题,这种情况在我工作过的公司中是普遍存在的,不仅会浪费时间排斥问题,还造成了很多的沟通成本,最致命的是本地运行好好的,到了线上就出现问题。

 由于我这次打算从最开始的部署环境步骤开始总结,所以不可避免的需要安装各种后端所需服务。我使用的是MacOS,在开发中确实好用,搭建环境也很方便,但问题是作为日常使用的电脑,MacOS会不定时的对系统进行更新,如果直接在上面搭环境的话很担心哪天因为系统更新了对某个服务会造成影响(虽然一直没有遇到过),还有就是希望把开发环境和日常使用的环境剥离开,方便管理和维护。所以最近很长时间以来都是使用虚拟机,在Linux上搭建开发环境。但问题又来了,最近使用我的虚拟机中的Linux时,发现精彩会卡死,一直也找不到问题,没办法只好卸载重新安装,又得从头再搭一次环境,浪费了很多时间,另外虚拟机占用的空间也偏大。

 这次我想不如试试Docker,之前大概了解过,但一直没有正儿八经的学习和使用它,这次借这个机会用用,刚好可以把我遇到的这两个问题都解决了。

以下内容我会基本搬运一些网上的教程,方便我日后自己查看。

什么是Docker

在介绍Docker之前,必须先说下Linux容器和虚拟机存在的缺点。

虚拟机和Linux容器

虚拟机

 虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。

虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。

  • 资源占用多
    虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。

  • 冗余步骤多
    虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。

  • 启动慢
    启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。

Linux容器

 由于虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。
**Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。**或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。
由于容器是进程级别的,相比虚拟机有很多优势。

  • 启动快
    容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。所以,启动容器相当于启动本机的一个进程,而不是启动一个操作系统,速度就快很多。

  • 占用资源少
    容器只占用需要的资源,不占用那些没有用到的资源;虚拟机由于是完整的操作系统,不可避免要占用所有资源。另外,多个容器可以共享资源,虚拟机都是独享资源。

  • 体积小
    容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。

总之,容器有点像轻量级的虚拟机,能够提供虚拟化的环境,但是成本开销小得多。

什么是Docker

 Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

可见Docker经常拿来与虚拟机作比较,下面这张图就是比较了Docker和传统虚拟机的不同之处:

 Docker将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了Docker,就不用担心环境问题。

 总体来说,Docker的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

核心概念

  • 镜像 image
    **Docker镜像(Image)就是一个只读的模板。**例如:一个镜像可以包含一个完整的操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序。
    镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
    就像以前我要给电脑重装Windows的话,会去网上下载各种Windows的镜像包,每个镜像包都有些不一样,除了Windows操作系统外,还会预装各种软件。
    镜像(Image)就是一堆只读层(read-only layer)的统一视角,也许这个定义有些难以理解,看看下面这张图:

右边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在docker宿主机的文件系统上访问到。统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

1
2
3
4
5
# 列出本机的所有 image 文件。
$ docker image ls

# 删除 image 文件
$ docker image rm [imageName]
  • 仓库 repository
    仓库(Respository)是集中存放镜像文件的场所。 有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。可以把公开仓库理解成Docker版的GitHub。用户也可以在本地创建私有仓库。
    当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。这和Git仓库有相似的理念。

  • 容器 container
    **Docker 利用容器(Container)来运行应用。**容器是从镜像创建的运行实例,类似对象和类的关系。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

1
2
3
4
5
# 列出本机正在运行的容器
$ docker container ls

# 列出本机所有容器,包括终止运行的容器
$ docker container ls --all

上面命令的输出结果之中,包括容器的 ID。很多地方都需要提供这个 ID,比如终止容器运行的docker container kill命令。

终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm命令删除。

1
$ docker container rm [containerID]

运行上面的命令之后,再使用docker container ls --all命令,就会发现被删除的容器文件已经消失了。

Docker实例

 了解完Docker的基本概念后,本来应该是安装教程,因为我用的MacOS,直接下载安装就可以了,这里我就不赘述了。接下来用最简单的“Hello World” image体验一下Docker。

首先需要将image文件从仓库拉取到本地:

1
$ docker image pull library/hello-world

$ docker image pull是抓取image文件的命令。
library/hello-world是image文件在仓库里面的位置,其中library是image文件所在的租,hello-world是image文件的名称。
由于 Docker 官方提供的 image 文件,都放在library组里面,所以它的是默认组,可以省略。

通过以下命令浏览本地的镜像

1
$ docker image ls

接着运行这个image文件

1
$ docker container run hello-world

docker container run命令会从image文件中生成一个正在运行的容器实例。
注意,docker container run命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的docker image pull命令并不是必需的步骤。
运行成功后就会在终端中读到一些输出

1
2
3
Hello from Docker!
This message shows that your installation appears to be working correctly.
......

输出这段提示以后,hello world就会停止运行,容器自动终止。
有些容器不会自动终止,因为提供的是服务。比如,安装运行 Ubuntu 的 image,就可以在命令行体验 Ubuntu 系统。

对于那些不会自动终止的容器,必须使用docker container kill命令手动终止。

1
$ docker container kill [containID]

如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !