[1/4] Dockerify:Docker 基础概念与实践

文章已合并进 e1200

全文2300字,阅读此文章,你可能需要一杯咖啡☕️~

笔者花生PeA,百度前端汪、ACGer。个人博客 pea3nut.blog;个人资料 pea3nut.info

在保留此段前提下,随意转载。请确保此段为文章最头部

本篇文章详细而又简短的介绍了:一名完全不了解 Docker 前端程序员,将全站 Docker 化的过程。内容主要包含:

  • Docker 基本概念
  • 真实站点迁移过程:
    • 静态站点
    • Nodejs 站点(Express)
    • WordPress(PHP)
  • 一些必备技巧:开机启动、常用Shell

文章会讲解使用 Docker 过程中用到的全部技术栈(Github CI、Nginx 反向代理、docker-compose),绝不会出现“详见:http://xxx”甩链接的情况。

无需再查阅其他文档,看着一篇就够了!

good

当前有哪些问题

手动部署成本太高

笔者维护了诸多网站,其中包含:

  • 我的简历:pea3nut.info,使用 Vuejs 构建的SPA单页应用,纯静态
  • 我的博客:pea3nut.blog,使用著名的WordPress搭建(PHP+Apache+MySQL)
  • 一个开源项目——Pxer:pxer.pea3nut.org,官网使用 Nodejs + Express SSR 搭建

而每次我想修改某个网站内容是十分麻烦的。拿大家熟悉的纯静态站点来说,修改过程如下:

  • 下载:从Github下载代码,然后本地npm install
  • 开发:npm run dev本地修改代码,测试
  • 编译:npm run build使用 Webpack 进行编译,产出静态资源
  • 上传:打开FTP软件,上传替换文件
  • 测试:看看网站是否在线上工作正常
  • 提交:将代码提交到 Github

哪怕我只是修改个错别字,都要十几分钟

网站太多,改动太频繁,而每次不管多小的改动都很麻烦。简直让我感觉自己在维护一个万级QPS的大型项目

某个服务挂了,我不懂 Linux 无法排查

最近我发现我的 MySQL 进程总是挂掉,导致所有依赖于MySQL的站点都挂了

我也不知道为什么,之前还是好好的

why

我尝试了重启进程、重启服务器、捞报错日志百度,均未奏效

好吧,其实我不太懂 Linux,也不太懂 MySQL,我只是想用下他们搭建 WordPress 站点。而最近总出问题,让我意识到:

我不仅要维护站点,我还要维护环境

这个对于我一名前端来说太难了,装个NVM就已经是我的极限了。MySQL无缘无故(起码在我看来是)挂掉,我根本没有能力查出个一二三四,然后解决它

我不仅要保证站点本地能跑通,还必须要部署在远程VPS稳定运行。。。

i-am-so-hard

重启不行。。。那就只能重装系统了

可是,由于搭建了许多站点,VPS服务器环境相当复杂(或许这个就是 MySQL 挂掉的原因),光 Apache 配置文件都几百行了。重做系统的迁移成本,光是想一想就耗光了我所有的勇气

新的技术方案——Docker

总结一下有如下问题:

  • 手动部署成本太高,改错别字都很麻烦
  • 一台服务器由于时间累积导致环境变得“脏乱差”
  • 重装系统成本太高,难以迁移

而 Docker,正是我解决所有问题SCP-500万能药

那么 Docker 是如何做的呢?

镜像与容器

Docker 中有两个重要概念。

一个是容器(Container):容器特别像一个虚拟机,容器中运行着一个完整的操作系统。可以在容器中装 Nodejs,可以执行npm install,可以做一切你当前操作系统能做的事情

另一个是镜像(Image):镜像是一个文件,它是用来创建容器的。如果你有装过 Windows 操作系统,那么 Docker 镜像特别像“Win7纯净版.rar”文件

上边就是你所需要了解的 Docker 全部基础知识。就这么简单

顺便一提,在 Docker 中,我们通常称你当前使用的真实操作系统为“宿主机”(Host)

安装 Docker

安装 Docker 在你的电脑上就像安装 VS Code 一样简单

如果你使用的是Windows电脑,需要购买支持虚拟化的版本。如Win10专业版,Win10家庭版是不行的

安装完Docker后,你可能会发现自己可以打开一个漂亮的 Docker 窗口。其实这个窗口没什么用处,通常我们都是通过CLI命令行的方式操作 Docker的,就像 Git 一样

运行 Docker

接下来我们搭建一个能够托管静态文件的 Nginx 服务器

容器运行程序,而容器哪来的呢?容器是镜像创建出来的。那镜像又是哪来的呢?

镜像是通过一个 Dockerfile 打包来的,它非常像我们前端的package.json文件

创建文件

我们创建一个目录hello-docker,在目录中创建一个index.html文件,内容为:

[code lang=html]
<h1>Hello docker</h1>
[/code]

然后再在目录中创建一个Dockerfile文件,内容为:

[code lang=bash]
FROM nginx

COPY ./index.html /usr/share/nginx/html/index.html

EXPOSE 80
[/code]

此时,你的文件结构应该是:

[code lang=text]
hello-docker
|____index.html
|____Dockerfile
[/code]

打包镜像

文件创建好了,现在我们就可以根据Dockerfile创建镜像了!

在命令行中(Windows优先使用PowerShell)键入:

[code lang=bash]
cd hello-docker/ # 进入刚刚的目录
docker image build ./ -t hello-docker:1.0.0 # 打包镜像
[/code]

注意!Docker 中的选项(Options)放的位置非常有讲究,docker —help imagedocker image —help是完全不同的命令

docker image build ./ -t hello-docker:1.0.0的意思是:基于路径./(当前路径)打包一个镜像,镜像的名字是hello-docker,版本号是1.0.0。该命令会自动寻找Dockerfile来打包出一个镜像

Tips: 你可以使用docker images来查看本机已有的镜像

不出意外,你应该能得到如下输出:

[code lang=text]
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM nginx
---> 5a3221f0137b
Step 2/3 : COPY ./index.html /usr/share/nginx/html/index.html
---> 1c433edd5891
Step 3/3 : EXPOSE 80
---> Running in c2ff9ec2e945
Removing intermediate container c2ff9ec2e945
---> f6a472c1b0a0
Successfully built f6a472c1b0a0
Successfully tagged hello-docker:1.0.0
[/code]

可以看到其运行了 Dockerfile 中的内容,现在我们简单拆解下:

  • FROM nginx:基于哪个镜像
  • COPY ./index.html /usr/share/nginx/html/index.html:将宿主机中的./index.html文件复制进容器里的/usr/share/nginx/html/index.html
  • EXPOSE 80:容器对外暴露80端口

运行容器

我们刚刚使用 Dockerfile 创建了一个镜像。现在有镜像了,接下来要根据镜像创建容器:

[code lang=bash]
docker container create -p 2333:80 hello-docker:1.0.0
docker container start xxx # xxx 为上一条命令运行得到的结果
[/code]

然后在浏览器打开127.0.0.1:2333,你应该能看到刚刚自己写的index.html内容

在上边第一个命令中,我们使用docker container create来创建基于hello-docker:1.0.0镜像的一个容器,使用-p来指定端口绑定——将容器中的80端口绑定在宿主机的2333端口。执行完该命令,会返回一个容器ID

而第二个命令,则是启动这个容器

启动后,就能通过访问本机的2333端口来达到访问容器内80端口的效果了

Tips: 你可以使用docker containers ls来查看当前运行的容器

当容器运行后,可以通过如下命令进入容器内部:

[code lang=bash]
docker container exec -it xxx /bin/bash # xxx 为容器ID
[/code]

原理实际上是启动了容器内的/bin/bash,此时你就可以通过bash shell与容器内交互了。就像远程连接了SSH一样

发生了什么

我们总结下都发生了什么:

  1. 写一个 Dockerfile
  2. 使用docker image build来将 Dockerfile 打包成镜像
  3. 使用docker container create来根据镜像创建一个容器
  4. 使用docker container start来启动一个创建好的容器

docker-works

虽然很简单,但是也没有感觉到“广阔天地,大有可为,为所欲为”呢?

  • 浏览:2225
  • 评论:1

发表新的回复


粗不粗 2019年9月17日 上午11:27

为所欲为!

回复