Docker X SystemD折腾向:用Docker手动安装Ghost博客的奇妙经历

前言


本来之前一直在简书平台上记录心得,但好友给我看了自己搭的Ghost博客,着实漂亮,恰逢计网附加作业是搭建一个个人网站,就有了趁这次机会搭一个博客并把部分文章迁移过去的想法

选择Ghost,一是因为自己之前搭建/维护的网页基本都是php,后来又接触了python的网络编程,想试试新东西——Ghost博客是基于node.js的框架,正好如我所愿;二是因为真的挺漂亮。

而选择Docker搭建的原因则比较现实了:我的学生服务器上还维护着几个其他项目,担心乱搞会搞崩原本的环境。虽然Ghost官方提供了现成的镜像可以一键部署,但是抱着学习的心态,还是选择了自己开一个ubuntu16.04的容器手动搭建。官方文档其实已经有非常详细的步骤,但是自己作死踩了不少坑,故作此记录

准备


下面是官方文档中提出的要求事实上看到第五项我就应该反应过来预想中的搭建方式肯定会出问题

  • Ubuntu 16.04 or Ubuntu 18.04
  • NGINX (minimum of 1.9.5 for SSL)
  • A supported version of Node.js
  • MySQL 5.5, 5.6, or 5.7 (not >= 8.0)
  • Systemd
  • A server with at least 1GB memory
  • A registered domain name

环境搭建


  • 容器启动

    为了日后维护方便用-p选项开了三个端口,其中2368是Ghost默认的端口。这里其实没有必要对此进行映射,映射后搭建完成后还是得开个反向代理监听2368,否则博客里许多地方都是默认跳转到localhost:2368的orz
    -it则是启动交互模式, -v设置共享文件夹
    docker run -it -v /docker:/docker -p 8168:2368 -p 8122:22 -p 8100:80 --privileged=true --name=m_ghost daocloud.io/library/ubuntu:latest /bin/bash
    
    
  • 初步环境配置

    由于容器是轻量化的虚拟技术,原本的设计意图是一个容器只运行一个应用,我们将其作为轻量虚拟机使用时需要手动安装很多ubuntu发行版已经自带的功能
    apt-get update
    apt-get upgrade
    apt-get install sudo
    apt-get install vim
    apt-get install openssh-server #安装ssh
    
    其中要提一下ssh,安装好后需要sudo vim /etc/sshd_config打开配置文件,并将PermitRootLogin一项前的注释去掉,把后面的参数改为yes,再service sshd start启动服务
  • 创建新用户

    Ghost博客出于安全考虑,不允许使用root用户安装,故此步是必需的
    adduser eva #eva是我设置的用户名,可在命名规则内随意更换
    usermod -aG sudo eva #添加到sudo用户组
    su eva #切换至该用户,后面步骤全部使用该用户进行
    
  • 安装nginx

    sudo apt-get install nginx
    
  • 安装mysql

    sudo apt-get install mysql-server
    
  • 安装Node.js

    此处需要注意安装对应版本的node.js,Ghost支持的版本一般会比最新版本晚一代,可以在官网查询
    curl -sL 'https://deb.nodesource.com/setup_10.x' | sudo -E bash #去掉引号再使用
    sudo apt-get install -y nodejs
    

安装Ghost


在新版本中我们得以使用官方安装工具Ghost-CLI来进行安装,免去了自己下载包、自己改配置文件的繁琐步骤当然也有会卡住的Bug

  • 安装Ghost-CLI

    sudo npm install ghost-cli@latest -g
    

    之后可以使用ghost help来获得帮助,并可以在flags and options查询更多选项与指令以个性化安装

  • 创建Ghost安装目录

    注意现在你不是root用户,在/root或/home下安装极有可能出错

    sudo mkdir -p /var/www/ghost #-p选项是为了确保有这个文件夹,没有则创建
    sudo chown eva:eva /var/www/ghost #改变文件夹所属用户与用户组
    sudo chmod 775 /var/www/ghost
    cd ghost #下一步操作也在ghost文件夹下进行
    
  • 安装Ghost

    ghost install
    

    这里有可能会卡在 Downloading and installing Ghost 这里,如果是卡在 Downloading 或者 Fetching packages,那就是服务器网不好,等待它自己重试即可;如果卡在 Building fresh packages 长达二十分钟多,那就是安装卡住了,需要按Ctrl+C退出安装,然后执行

    ghost uninstall
    cd..
    sudo rm -rf ghost
    

    然后从创建文件夹那一步重新开始按流程做
    如果安装正常进行的话,就会让你自定义一些信息。

    Enter your blog URL: (http://localhost:2368)
    Enter your MySQL hostname: (localhost)
    Enter your MySQL username:
    Enter your MySQL password:
    Enter your Ghost database name:
    Do you wish to set up "ghost" mysql user?
    Do you wish to set up Nginx?
    Do you wish to set up SSL?
    Set up Systemd?
    

    到这里都是按官网文档安装即可,基本上懒得设置的话一路默认下去,如果是正常安装的话到这里基本就没啥事了,安装完后登录url就能看到页面了,阿里云服务器的话别忘了到控制台安全组开放端口就行
    但是标题都是折腾向了怎么可能平安无事呢(笑

踩坑:Systemd


在刚刚的Set up Systemd?那一步时,我按照官网的推荐选了yes,然后就喜闻乐见的报错退出了

image.png

结合之前的项目经历,一股不详的预感油然而生

  • Systemd是什么?

    Systemd是一个系统管理守护进程、工具和库的集合,用于取代System V初始进程。Systemd的功能是用于集中管理和配置类UNIX系统。
    Systemd 的核心是一个叫单元unit的概念,它是一些存有关于服务service(在运行在后台的程序)、设备、挂载点、和操作系统其他方面信息的配置文件。Systemd 的其中一个目标就是简化这些事物之间的相互作用,因此如果你有程序需要在某个挂载点被创建或某个设备被接入后开始运行,Systemd 可以让这一切正常运作起来变得相当容易。(在没有 Systemd 的日子里,要使用脚本来把这些事情调配好,那可是相当丑陋的。)

    简单来说就是一个启动系统的时候用于管理各种服务的进程。在还没有systemd的时候,内核会去运行/sbin/init,随后这个程序会在名为 SysVinit 的系统中运行其余的各种启动脚本。现在Systemd则取而代之成为了第一个执行的进程,理所当然的,她的PID为1

  • 为什么会报错:容器与虚拟机的区别

    如上所述,我们来查看一下当前容器内的第一个进程是什么

    sudo ps -p 1
    

    然后发现PID为1的进程是/bin/bash!为什么会这样呢?
    要搞清楚原因,先得重新回顾一下Docker的设计意图与特点

    Docker最早是使用一种被称为LXC的容器技术,后来改用runC,另一方面,Docker的最大特色之一是被称为AuFS的分层文件系统。每一个镜像都会先创建一个只读的文件层,而每一个基于其的容器则不断往上添加新的文件层,每层存储的是其与镜像所不同的地方。

    该特性使得容器非常的轻量,甚至允许上千个基于同一镜像的容器共享区区1Gb的空间,这是传统VM不可能做到的。

    Docker没有传统意义上的内核,其虚拟化并不像传统虚拟机一样使用数套不同的硬件驱动、初始化进程、加载模块等,更很少像虚拟机一样各自拥有一整套系统资源,而是通过“命名空间”的技术隔离进程。一般地,容器和宿主系统共用同一套内核。因此,容器在轻量化的同时,也导致了其隔离性的缺乏

    比起一个虚拟机,Docker的概念其实更接近于一般讲的进程沙箱,例如OJ里常用来防止提交的代码危害系统安全的那种。虽然用起来和轻量化的虚拟机无异,但是和虚拟机还是有着巨大的不同,其设计意图也不是想在每一个容器内跑一个完整的系统,而是在每一个容器内跑一个单独的进程/应用,使得其在批量化测试、快速部署/迁移等场合有着亮眼的表现。像我过去一样把docker当成虚拟机一样使用、在每个容器里部署一套笨重的LNMP无疑是越俎代庖的行为
    这也解释了为什么会报错:我启动的容器并没有、也不需要systemd这种用来在启动时管理加载过程的进程,在她眼里,自己的存在只是为了运行run命令时输入的/bin/bash而已。
    关于这块更多的知识,可以参考StackOverflow的这个回答

    • 如何解决

      1.在本不存在SystemD的系统里模拟一个能执行systemctl的脚本
      有一个优秀的项目叫docker-systemctl-replacement,通过重写/bin/systemctl使得进程能在没有systemd的情况下使用systemctl启动和停止服务
      具体用法举例如下
      wget https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py -O /usr/local/bin/systemctl
    
    

    然而我们并不是需要systemctl命令来管理服务,而是Ghost框架需要依赖SystemD本身,所以根本没用

    2.在启动容器时将/sbin/int作为启动命令,并使用privileged=true来赋予其访问宿主系统内核的权限

    例如

    docker run -d -v /docker:/docker -p 8168:2368 -p 8122:22 -p 8100:80 --privileged=true --name=m_ghost daocloud.io/library/ubuntu:latest /sbin/init
    
    

    然而依旧报错,镜像里根本就没有/sbin/init......
    但是没有关西!我在这之前把自己配好的环境commit成了一个镜像,那个镜像是可以成功启动的,而且pid1也是/sbin/init
    但是那个容器里面的mysql坏掉了....出现了如下报错

    Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
    

    而且网上对此的解决方案都毫无用处....

    3.使用官方镜像

    老实说这样根本就没有解决问题嘛....有时间去研究下它的Dockerfile好了
    顺带一提直接用其Dockerfile来build镜像会出问题,意义不明

At Last


最后我还是使用了官方镜像....
具体操作如下

docker pull ghost
docker run -d -v /docker:/docker -p 8168:2368 -p 8122:22 -p 8100:80 --name=m_ghost ghost
# 注意最后不用跟任何命令

唔然后就搭起来啦...接下来的事情就只有进入我的博客主页然后按说明慢慢配置各项主题、设计等等了
暂时没有域名so配置代理、配置SSL证书啥的都先搁置了,有需要的可以参考这里
结果最后也没有解决systemd和mysql的问题....是时候好好读一读操作系统原理了XD

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341