玩转Docker实战篇!使用Docker构建Apache+Jekyll博客网站,附加介绍卷的备份

一、本文目的

  • 本文新增的Docker知识点有:
    • Dockerfile中VOLUME指令的使用
    • Dockerfile中WORKDIR指令的使用
    • docker run中--volumes-from选项的使用:使一个容器的目录挂载到另一个容器中
    • docker run中--rm选项的使用:容器只运行一次,随后立即删除
    • Docker容器卷的备份
  • 本文构建一个使用Jekyll框架(https://jekyllrb.com/)的自定义网站
  • 本文会构造两个镜像:
    • 一个镜像安装了Jekyll及其他用于构建Jekyll网站的必要的软件包
    • 一个镜像通过Apache来让Jekyll网站工作起来
  • 本文的总体工作流程是:
    • 创建Jekyll基础镜像和Apache镜像(只需要构建一次)
    • 从Jekyll镜像创建一个容器,这个容器存放通过卷挂载的网站源代码
    • 从Apache镜像创建一个容器,这个容器利用包含编译后的网站的卷,并为其服务
    • 在网站需要更新时,清理并重复上面的步骤

本文的代码、文件链接

二、构建Jekyll容器

①创建目录

  • 创建一个jekyll目录,作为本文整体的一个工作目录,然后进入jekyll目录再创建一个jekyll目录,作为构建jekyll的工作路径
mkdir jekyll

cd jekyll

mkdir jekyll

ls

cd jekyll

②创建Dockerfile

  • 在jekyll/jekyll目录下创建一个Dockfile文件,用于构建包含jekyll服务的镜像,文件的内容如下:
    • FROM指令:基于ubuntu 16.04构建该镜像
    • LABEL指令:为容器添加元数据,此处为添加镜像的作者和地址(此处添加了我的博客地址)。LABEL指令详情请参阅:https://blog.csdn.net/qq_41453285/article/details/107389320
    • ENV指令:为了重新构建缓存,详情请参阅前文的“基于构建缓存的Dockerfile模板”专题:https://blog.csdn.net/qq_41453285/article/details/107389320
    • 3条RUN指令:更新软件包、安装Ruby和用于支持Jekyll的包
    • 2条VOLUME指令:基于该镜像创建的容器,会在容器中会创建了两个卷目录:
      • /data/:用来存放网站的源代码,在文章下面我们会将宿主机中Jekyll的源代码目录挂载到这个目录下
      • /var/www/html/:用来存放编译后的Jekyll网站码
    • WORKDIR指令:将/data/设置为工作目录,下面的ENTRYPOINT指令用到的工作目录就是这个
    • ENTRYPOINT指令:
      • 此指令是用来执行一条命令的,当基于该镜像的容器运行时会执行该命令
      • 此处为使用jekyll命令进行构建,其将/data/中的所有的Jekyll网站代码编译构建到/var/www/html目录中
vim Dockerfile
FROM ubuntu:16.04
LABEL maintainer="https://blog.csdn.net/qq_41453285"
ENV REFRESHED_AT 2020-07-27

RUN apt-get -qq update
RUN apt-get -qq install ruby ruby-dev libffi-dev build-essential nodejs
RUN gem install --no-rdoc --no-ri jekyll -v 2.5.3

VOLUME /data
VOLUME /var/www/html
WORKDIR /data

ENTRYPOINT [ "jekyll", "build", "--destination=/var/www/html" ]

  • 现在jekyll目录下只有一个Dockerfile文件

③构建镜像

  • 第一步:基于上面的Dockerfile文件,我们创建一个镜像,镜像取名为“dongshao/jekyll”
sudo docker build -t dongshao/jekyll .

  • 构建可能需要一定的时间,构建完成之后如下所示:

  • 第二步:查看新创建的镜像
sudo docker images

三、构建Apache容器

①创建目录

  • 从上面的工作目录回到顶级目录,在jekyll目录下创建一个apache目录,用于存放Apache相关的配置文件
cd ..

mkdir apache

ls

cd apache

②创建Dockerfile

  • 在jekyll/apache目录下创建一个Dockfile文件,用于构建包含apache服务的镜像,文件的内容如下:
    • FROM指令:基于ubuntu 16.04构建该镜像
    • LABEL指令:为容器添加元数据,此处为添加镜像的作者和地址(此处添加了我的博客地址)。LABEL指令详情请参阅:https://blog.csdn.net/qq_41453285/article/details/107389320
    • ENV指令:为了重新构建缓存,详情请参阅前文的“基于构建缓存的Dockerfile模板”专题:https://blog.csdn.net/qq_41453285/article/details/107389320
    • 2条ENV指令:更新软件包、安装Apache
    • VOLUME指令:在容器中创建了卷,此处为/var/www/html,用来存放编译后的Jekyll网站(但是此处实际并没有创建,而是用"docker run"的"--volumes-from"选项挂载到了james_blog容器中,见下面介绍)
    • WORKDIR指令:将/var/www/html设置为工作目录
    • 6条ENV指令:设置一些必要的环境变量
    • RUN指令:创建必要的目录
    • EXPOSE指令:将基于该镜像构建的容器的80端口映射到宿主机中
    • ENTRYPOINT指令、CMD指令:使用这两条命令的组合,当容器启动时会执行这条命令,从而启动运行Apache
vim Dockerfile
FROM ubuntu:16.04
LABEL maintainer="https://blog.csdn.net/qq_41453285"
ENV REFRESHED_AT 2020-07-27

RUN apt-get -qq update
RUN apt-get -qq install apache2

VOLUME [ "/var/www/html" ]
WORKDIR /var/www/html

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2

RUN mkdir -p $APACHE_RUN_DIR $APACHE_LOCK_DIR $APACHE_LOG_DIR

EXPOSE 80

ENTRYPOINT [ "/usr/sbin/apachectl" ]
CMD ["-D", "FOREGROUND"]

  • 现在apache目录下只有一个Dockerfile文件

③构建镜像

  • 第一步:基于上面的Dockerfile文件,我们创建一个镜像,镜像取名为“dongshao/apache”
sudo docker build -t dongshao/apache .

  • 构建可能需要一定的时间,构建完成之后如下所示:

  • 第二步:查看新创建的镜像
sudo docker images

四、启动Jekyll网站

  • 现在我们的宿主机中有以下两个镜像:
    • dongshao/jekyll:安装了Ruby及其他必备软件包的Jekyll镜像
    • dongshao/apache:通过Apache Web服务器来让Jekyll网站工作起来的镜像

①下载Jekyll博客源代码

  • 下面我们将Jekyll博客的源代码下载自己的家目录下(你们随意放在哪里都行)
cd $HOME

git clone https://github.com/jamtur01/james_blog.git

ls james_blog

  • 这个目录下是博客网站的源代码,是一个启动了Twitter Bootstrap的最基础的Jekyll博客。你也可以自己修改_config.yml文件和主题,以符合你的要求

②创建Jekyll容器

  • 第一步:下面创建一个Jekyll容器,命令如下:
    • -v:将宿主机的目录作为卷,挂在到容器中。此处我们把宿主机的Jekyll博客的源代码目录(/home/ubuntu/james_blog)挂在到容器的“/data/”目录
    • --name:容器的名字,此处起名为james_blog
    • 最后一个选项:为上面创建的“dongshao/jekyll”镜像
sudo docker run -v /home/ubuntu/james_blog:/data/ --name james_blog dongshao/jekyll

  • 关于上面-v选项的详解:
    • 上面我们将/home/ubuntu/james_blog挂载到容器的/data/目录下
    • 当容器运行时,会执行“dongshao/jekyll”镜像的Dockerfile所指定的ENTRYPOINT指令
    • ENTRYPOINT指令会在/data目录下工作,调用jekyll命令对/data/目录下的网站源代码进行构建,然后将构造好的网站存放到/var/www/html目录下
    • 下面的Apache容器会来访问/var/www/html目录下编译好的网站(见下)

  • 第二步:查看新创建的容器(运行一会儿后就会自动退出,因为构建完成后就退出了)
# 查看当前正在运行的容器
sudo docker ps

③启动Apache容器

  • 启动命令如下:
  • -d:让该容器以守护进程的方式在宿主机中运行
  • -P:该选项可以用来对外公开在Dockerfile中通过EXPOSE指令公开的所有端口。上面我们"dongshao/apache"镜像的Dockerfile中公开了80端口,此处我们就使用该选项将容器的80端口映射到宿主机的任意端口上
  • --volumes-from:
    • 该选项为把指定容器里的所有卷都加入到新创建的容器里,此处我们把james_blog容器的卷都加入到这个新创建的容器中
    • 所以,该容器可以访问上面创建的james_blog容器里的/var/www/html卷
    • 另外,我们上面apache的Dockerfile文件中使用到了/var/www/html目录,因此其访问的就是james_blog容器中的/var/www/html目录,又因为/var/www/html目录下存放了编译好的Jekyll网站,因此Apache服务器就可以运行这个博客网站
  • 最后一个选项:为上面创建的“dongshao/apache”镜像
sudo docker run -d -P --volumes-from james_blog dongshao/apache
  • --volumes-from的备注:
    • 上面我们使用这个选项,让Apache容器访问了james_blog容器中的卷
    • 即使james_blog容器没有运行,我们也可以使用这个卷,因此即使james_blog容器没有运行我们也可以访问/var/www/html目录下的网站程序,这是Docker的特性
  • 第二步:查看新创建的容器
# 查看当前正在运行的容器
sudo docker ps

④问Apache服务器

  • 第一步:上面我们把Apache容器的80端口映射到宿主机中了,下面查看映射的端口为多少
sudo docker port 6dd91f973d9b

  • 第二步:通过这个端口去访问Apache容器中运行的Apache服务器,命令如下:

五、修改Jekyll博客网站

  • 如果想要修改网站的数据,直接在宿主机中修改Jekyll博客的源代码,然后重启james_blog容器让其重新编译即可
  • 第一步:例如,下面我们修改james_blog/_config.yml文件来修改博客的名字
vim ~/james_blog/_config.yml

  • 第二步:修改完成之后重启james_blog容器
sudo docker start james_blog

  • 第三步:查看james_blog容器的日志,可以看到该容器重新编译了/data/下的网站
sudo docker logs james_blog

  • 编译完成之后不需要重启Apache容器
  • 第四步:但是刷新之后发现网站并没有变化,我猜想可能是因为james_blog容器编译出错了(见上图最后一行的“Auto-regeneration”提示)

  • 算了,这个问题就不解决了,我也不太知道是什么原因导致网站编译没有通过

六、备份Jekyll卷

  • 如果我们不小心删除了卷(尽管可以轻松地重建这个卷)。由于卷的优点之一就是可以挂在到任何容器,因此可以轻松备份它们
  • 第一步:现在我们重新构建一个容器,用来备份/var/www/html卷,代码如下所示:
    • --rm:指明创建的这个容器只用一次,运行完成之后就删除该容器
    • --volumes-from:该选项为把指定容器里的所有卷都加入到新创建的容器里,此处我们把james_blog容器的卷都加入到这个新创建的容器中
    • -v:将宿主机的当前目录挂载到该容器的/backup目录下
    • "tar ...."命令:
      • 后面的这条命令使用在启动容器时,在容器中执行的
      • 此处我们将/var/www/html/目录下(映射到james_blog容器中的目录)的所有内容打包,然后存放到当前容器的/backup/目录下,名为james_blog_backup.tar
      • 又因为容器的/backup目录映射到了宿主机的当前路径下(-v选项),所有打包的文件会在宿主机的当前路径下(见下)
sudo docker run --rm --volumes-from james_blog -v $(pwd):/backup ubuntu tar cvf /backup/james_blog_backup.tar /var/www/html

  • 第二步:通过查看当前宿主机,可以看到容器打包的文件存放到了当前路径下
ls james_blog_backup.tar

  • 这是一个简单的备份过程,用户可以扩展这个命令,备份到本地存储或者云端(如Amazon S3或者更传统的类似Amanda的备份软件)存储

七、扩展Jekyll网站

  • 下面是几种扩展Jekyll网站的方法:
    • 运行多个Apache容器,这些容器都使用来自james_blog容器的卷。在这些Apache容器前面加一个负载均衡期,我们就拥有了一个Web集群
    • 进一步构建一个镜像,这个镜像把用户提供的源数据赋值(如通过git clone)到卷里。再把这个卷挂在到从dongshao/jekyll镜像创建的容器。这就是一个可迁移的通用方案,而且不需要宿主机本地包含任何源代码
    • 在上一个扩展基础上可以很容易为我们的服务构建一个Web前端,这个服务用于从指定的源自动构建和部署网站。这样用户就有一个完全属于自己的GitHub Pages了。

  • 我是小董,V公众点击"笔记白嫖"解锁更多【Docker】资料内容。

相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页