仔细想想还是 Dockerized 吧!

The AI Lab of my mentor was running by me for quite some months. And now it's about time to hand over the docs of the internal server to graduates. Though one of which tends to lose internet connection from time to time due to its location. However, I heart that it had been moved back to university in the middle of July.

And originally, I use Microsoft Word to keep all the records and information of almost everything, but it obviously would cause some issues.

For example, one's docs version may vary from another. Yes, I've thought about to use the cloud storage with version control even. The problem is that we cannot afford the expense of cloud drive. And we could not find someone who's willing to take the charge of reimbursement. The bills have already piled up in my mentor's desk.

Besides that, to use file as docs will inevitably introduce the ugly naming, such as docs-20190807, docs-20190607 or whatever. And it would be totally disaster if to use git for version control. Despite of the unreadable commits, the filename needs to be the same, which extremely likely to be ignored to update from the git repo for some people.

Luckily, there's one instance on AliCloud (Although personally I don't really like AliCloud, but that's another story, let's save it for next time). And lots of packages that can generate static HTML from markdown have been developed these years around.

It would be easy for everyone to access docs online and because the markdown file is pure text, we can have a very good and most important, readable track of changes with git.

The final decision is to use VuePress as the static HTML generator. And to ensure a simple installation process, dockerization is the best shot at the moment. Furthermore, basic HTTP auth is needed to keep unwanted visitors out, leaving the docs only accessible to the lab.

For your convenience, this project is located at my GitHub, #/docs. It's fully prepared and dockerized with docker-compose support.

To install VuePress, nodejs > 8.0 is required. Personally, I tend to use nvm to install nodejs. The installation is easy.

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
NVM_DIR="${HOME}/.nvm"
\. "\$NVM_DIR/nvm.sh" && nvm install node

As for the package manager of node, yarn is my favorite. Here is the demonstration of installing yarn and using yarn to install the packages we need.

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn && \
    yarn global add vuepress

And codes might occur in the docs, so syntax highlighting is a necessary for readability.

yarn add highlight.js [email protected]

The usage of VuePress is painless. Just place the markdown files accordingly in a directory, and the README.md is default entry of VuePress.

.
└─ docs
   ├─ README.md
   ├─ detail.md
   └─ keys.md

Generating static HTML can be easily done by one line command

vuepress build docs

And a .vuepress subdirectory would be created in docs, which contains the static HTML files in dist.

.
└─ docs
   ├─ README.md
   ├─ detail.md
   ├─ keys.md
   └─ .vuepress
      └─ dist
         ├─ 404.html
         ├─ index.html
         └─ assets
            └─ ...

But to enable syntax highlighting, another script is required.

import VueHighlightJS from 'vue-highlight.js';
import 'highlight.js/styles/dark.css';
export default ({
    Vue, 
}) => {
    Vue.use(VueHighlightJS)
}

The script is placed at docs/.vuepress/hl.js. And the content above is pretty much how we would use VuePress. Which also leads us to the following dockerization.

The process of dockerization is quite straightforward. And I'll paste the Dockerfile with comments below.

# Distributed under the terms of the Modified BSD License.
# Copyright (c)[data deleted].

FROM ubuntu:18.04

MAINTAINER BlueRyza"[data deleted]"

# if you were in China
RUN sed -i 's/cn.archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && \
    sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && \
    apt-get update

# curl: downloading GPG key of yarn and nvm install script
# git: nvm installation will use that
# gnupg: to add/verify the GPG key of yarn
# nginx: to serve the static HTML generated by VuePress
# openssl: generate passwd for basic HTTP auth
# apt-transport-https, 
# ca-certificates: yarn https repo
RUN apt-get install -y apt-transport-https ca-certificates curl git gnupg nginx openssl

# install nvm
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
# environment variable for nvm
ENV NVM_DIR "/root/.nvm"
# load nvm and install latest nodejs
RUN \. "\$NVM_DIR/nvm.sh" && nvm install node

# docs
RUN mkdir -p /root/docs
WORKDIR /root

# add yarn GPG key
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
# install yarn 
# and use yarn to install vuepress later
# besides, there might be codes in docs
# so syntax highlighting is added
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn && \
    yarn global add vuepress && \
    yarn add highlight.js [email protected]

# hightlight script for vuepress
ADD hl.js /root/hl.js

# nginx conf
ADD docs.conf /root/docs.conf
RUN cp -f /root/docs.conf /etc/nginx/sites-available/docs.conf && \
    ln -s /etc/nginx/sites-available/docs.conf /etc/nginx/sites-enabled/docs.conf && \
    rm -f /etc/nginx/sites-enabled/default && \
    rm -f /etc/nginx/sites-available/default && \
    sed -i 's/www-data/root/g' /etc/nginx/nginx.conf

# basic HTTP auth
ADD htpasswd.sh /root/htpasswd.sh
RUN chmod +x /root/htpasswd.sh

EXPOSE 80
ENTRYPOINT /root/htpasswd.sh && mkdir -p /root/docs/.vuepress && cp /root/hl.js /root/docs/.vuepress/hl.js && vuepress build docs && nginx -g 'daemon off;'

Given that we need basic HTTP auth, and also to make this project more generalized, a script named htpasswd.sh would serve the purpose.

It firstly checks whether there is a /root/docs/security.txt file. And the content of the /root/docs/security.txt follows the below format.

USER1 PASSWORD1
USER2 PASSWORD2

Please note that, there has to be a blank line at the end. And no space-ish character is allowed in either username or password. Moreover, : is also prohibited in username.

If there's no /root/docs/security.txt file, htpasswd.sh would check /root/docs/.htpasswd file. Thus we allow users to generate .htpasswd compatible lines in advance, without the concern of leaking plain password in /root/docs/security.txt.

And if both /root/docs/security.txt and /root/docs/.htpasswd are missing, the basic HTTP auth is disabled automatically. This would satisfy most users.

Leave a Reply

Your email address will not be published. Required fields are marked *

twenty + 4 =