NodeJS 和 Ghost 的 Dockerfile

Aug 30, 2015

虽然在 Docker Hub 看到有标注 OFFICIAL REPOSITORY 的 Dockerfile,但是我还是想自己写一个,因为他们的 Dockerfile 里有一个叫 docker-entrypoint.sh 的文件包含以下内容:

  if [ ! -e "$GHOST_CONTENT/config.js" ]; then
    sed -r '
      s/127\.0\.0\.1/0.0.0.0/g;
      s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g;
    ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js"
  fi

这里会把所有 config.js 里的 127.0.0.1 替换为 0.0.0.0 以允许外网访问,却并没有提供数据库的自定义设置。我不想用 SQLite,所以希望能自定义一下 config.js,干脆自己动手。

NodeJS

首先写一个 NodeJS 环境的 Dockerfile,这样下次要用到 NodeJS 我可以直接引用它:

FROM ubuntu:latest

MAINTAINER Evlos <[email protected]>

ADD sources.list /etc/apt/sources.list
RUN apt-get update && \
  apt-get -y upgrade && \
  DEBIAN_FRONTEND=noninteractive apt-get -y install curl && \
  curl --silent --location https://deb.nodesource.com/setup_0.12 | sudo bash - && \
  DEBIAN_FRONTEND=noninteractive apt-get -y install nodejs

我这里写了 ADD sources.list /etc/apt/sources.list,这样如果是阿里云的环境,在执行 docker build 之前可以先用 cp /etc/apt/sources.list ./ 把系统的 sources.list 放到当前目录,在执行 docker build 之后会被自动添加到容器中,以加速 apt-get

接下来按照 NodeJS 官方 Wiki 的教程安装,之前我还画蛇添足写上了 apt-get -y install npm 导致无法 build,因为从 NodeJS v0.10.0 开始 nodejs 直接包含了 npm,所以不需要单独安装。

Ghost

完成 NodeJS 的 Dockerfile 之后就开始写 Ghost 的 Dockerfile,其实 Dockerfile 除了其语法不一样一点,大部分都是 shell script,就不多解释了。

FROM evlos/nodejs

MAINTAINER Evlos <[email protected]>

ADD sources.list /etc/apt/sources.list
RUN apt-get update && \
  apt-get -y upgrade && \
  DEBIAN_FRONTEND=noninteractive apt-get -y install curl unzip && \
  mkdir -p /app && \
  cd /app && \
  curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip && \
  unzip -uo ghost.zip && \
  rm *.zip && \
  npm install --production && \
  mv /app/content /app/content_ && \
  mkdir /app/content

ENV NODE_ENV production
ADD config.js /app/config.js
ADD start.sh /app/start.sh
VOLUME ["/app/content"]
WORKDIR /app

EXPOSE 2368
CMD ["bash", "/app/start.sh"]

我用 mv /app/content /app/content_content 文件夹改成 content_ 的原因是因为之后要把 /app/content 这个路径作为 VOLUME 连接容器外的指定路径,这样数据文件就可以存在容器外面了。而据我所知使用 docker 的 -v 参数会导致容器内指定文件夹被重建,导致里面的数据消失,所有一开始需要把里面的数据移走,然后我的 Ghost 启动脚本会把内容在启动的时候再移回来:

if [ -d "/app/content_" ]; then
  cp -R /app/content_/* /app/content/
  rm -rf /app/content_
fi

NODE_ENV=${NODE_ENV:-production} npm start

另外我把 Ghost 自带的 config.example.js 重命名为 config.js 放在 Dockerfile 目录里,再用 ADD config.js /app/config.js 让它在 build 的时候自动添加 config.js。因为一般配置文件的格式在接下来的升级里并不会有太大改变,如果有改变再更新这个文件。在 docker build 之前自定义一下 config.js 的内容,先设置好数据库再 build 即可。

Summary

总的来说要执行以下命令完成 Ghost 的安装:

git clone https://github.com/Evlos/dockerfile.git
cd dockerfile

cd nodejs
rm sources.list
cp /etc/apt/sources.list ./
docker build -t evlos/nodejs .

cd ../ghost
vim config.js
rm sources.list
cp /etc/apt/sources.list ./
docker build -t evlos/ghost .
docker run -d -v /root/storage/ghost:/app/content -p 8080:2368 evlos/ghost

如果你只是用 SQLite 并且 VPS 在国外只需要一行就可以了,因为我已经把镜像发布到 Docker hub 上啦:

docker run -d -v /root/storage/ghost:/app/content -p 8080:2368 evlos/ghost

这里把 /root/storage/ghost 改成你要设置的数据文件在当前系统的存储路径,/root/storage/ 必须是已存在的文件夹,8080 改成你要开放的端口即可。


[back]