最开始接触到docker大概是四月中旬,我看到了buyVM的这款便宜的vps,然后当时正因为各种rss服务都不太满意,所以想自己搭建,于是就花了十块钱来了一个月的,并根据教程搭建了miniflux和rsshub的服务。教程中用的就是docke来部署miniflux的服务的。同时也因为学的这个教程,所以我当时的caddy才会部署在本地,而不是也通过docker来部署。

之后玩vps玩得兴起,同时又因为miniflux不能像tiny tiny rss那样根据每个rss源单独阅读,我又部署了ttrss。毕竟我关注的源中有几个经常刷大量的我不感兴趣的消息,但是又经常会看,所以才需要单独阅读。这样我闲着了就可以看看,没空了就可以先不看。后来为了看某个人的微博,我想要部署rss-bridge。但是我当时对于网站的目录结构并没有什么理解,所以他说要把代码放到网站的根目录,我就真的理解为,首先我需要一个网站,然后才能使用。再加上之前为了翻墙,所以我在freenom上面注册过域名,我干脆又找了一个教程搭建了这个基于typecho的博客。之后花了两天时间自己写了一个rss-bridge的桥,虽然后来我放弃了关注那个人的微博。在之后我又看到nextcloud的介绍,于是在这里部署了nextcloud。

终于前不久,这些东西搅一块之后我晕掉了,删掉了ttrss的数据库。于是由于之前使用docker的良好体验,我决定把以上服务都部署到一个docker-compose文件中,于是折腾了整整一个周末。在这个过程中,我发现最大的阻碍在于我对docker的理解还有caddy反代机制的理解,如果没有这两个阻碍,那么很可能我只要半天时间就可以完成部署。

接下来介绍一下docker。我对于docker一开始并没有什么理解,笑,后来用着觉得很舒服,于是才开始在网上寻找相应的教程。在我的使用中,docker更像是虚拟机的一个替代品,就像是实验室环境一样,可以有效地控制运行应用地环境,同时docker又远比虚拟机要轻量得多。一般来说,如果是日常使用的软件还好,都经过了很多调试,可以保证在各种环境中都正常使用,很少出现BUG。但是当使用开发软件的时候,由于各种配置过于复杂,而且很多时候还有很多奇奇怪怪的依赖,经常会因为各种原因跑不起来。尤其是对于我这种新手,本来就对于所使用的软件不够了解,如果再因为环境配置而出现问题的话,那么真的是有种要死的冲动了。之前就发生过一次类似的事情,我使用的某个软件出现一个我无法解决的问题,最后在GitHub上发现,原因是软件本身的缺陷。

所以使用docker,尤其是dockerhub上别人已经配置好了的镜像,几乎可以完全排除因为环境配置出错的可能性了。如果出现问题也不需要大动干戈地重启电脑,只需要简单的一句docker restart <容器名字或者ID>就可以轻松完成重启。甚至当容器中的配置也被自己玩坏了,还可以简单的重新从镜像中构建容器。如果是用的docker-compose那么就更轻松了,docker-compose downdocker-compose up -d就可以重新安装docker-compose.yml中所有的软件。这也是我一定要把自己的所有应用都整合到一个docker-compose.yml文件中去的主要原因,在两天的调试过程中,这两个命令也是我的大救星,没有他们,我不知道自己要花多长时间在调试具体的软件配置上面,尤其是一次次地修改,每一次都会遗留一些东西,最后把整个软件都搞崩,才是最可能的结果。

docker的图标是一个鲸鱼,背上有许多的集装箱。docker就像是整个鲸鱼,承载着许多的容器,像是集装箱一样,运行在其中。这里不涉及镜像的概念。在运行中的时候,docker就是一个环境,在这个环境中,一个个彼此相对独立的应用在自己的环境中运行,就是容器。每一个容易都有自己运行所需的环境,通过docker exec -it <容器名字或者ID> sh就可以进入到该容器的内部环境之中,接下来的操作就好像是在一个linux环境中运行的应用一样。事实上,很多容器中的确也包含有一个简单的linux系统,虽然一般都是去掉了各种不必要的组件的精简版。比如我所使用的caddy-alpine就只有几十M,算下来比我的Chrome浏览器还小。
caddy-alpine
当然也有复杂的,比如windows环境中的caddy,如果要安装的话,其中要包含一个windows的镜像,所以大小就难以控制了。
caddy-latest

这里就要涉及另一个概念了,镜像。

首先要理解一个思想,万物皆文件的思想,这也是Linux的核心思想。按照这种理解,我们运行的软件也是一种文件,只不过是存储在内存当中而已。一个文件从制作者发布到我们的使用,其中有几次变化。首先是制作者发布,我们下载,这仅仅是文件位置的变化,文件的内容和组织形式都没有发生任何的改变。之后是我们把这个软件安装到自己的电脑上,这里的安装实际上就是安装程序把我们下载下来的文件中的内容分别放到我们电脑上对应的位置里,创建一些运行中需要的文件,在必要的地方留下对应的信息,比如注册表。这个时候软件也就可以使用了,当我们点开软件,在这个过程中,电脑的操作系统把放到相应位置上的文件读取到内存当中,并在CPU中分配一定的资源,然后根据我们的交互行为产生不同的结果展示出来。

在docker中,镜像就相当于一个已经安装好了的软件包括它的操作系统环境,容器就相当于一个运行在内存中的软件。当然其中还有不小的差别,但是对于我这种新手来说,这种理解还是很有帮助的。

当我们用docker运行一个软件的时候,它会检查本地是否有对应的镜像,没有的话,会按照我们的设置去其他地方寻找镜像,默认是dockerhub。Docker程序寻找到对应的镜像之后就会把它下载到本地,这时本地就有了我们要运行的镜像。然后docker通过某种方式创建一个容器,这时容器应该还没有进入内存,我们可以称之为离线容器。然后docker把这个容器加载到内存当中开始运行,这时可以称之为在线容器。

这里就要说明之前提到的几个命令了。docker restart命令就是停止运行对应的容器,然后重新启动对应的容器,但是在这个过程中docker不会保留你已经修改的配置,所以实际上还需要进行目录挂载来解决这个问题。这个重启实际上就可以等同于我们自己电脑上的关机重启。而通过docker-compose up启动的过程是这样的,首先docker-compose.yml文件中记录有我们要运行的软件的镜像,所以它会先下载这个镜像到本地,然后创建出对应的容器并开始运行。docker-compose down命令则是暂停并删除全部的容器,区别于docker stop命令并不删除离线容器。

之后还有docker容器之间的通信,docker-compose.yml文件的相关信息,我会在以后的博客中写(大概)。