一、本文目的
- 本文新增的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镜像创建一个容器,这个容器利用包含编译后的网站的卷,并为其服务
- 在网站需要更新时,清理并重复上面的步骤
本文的代码、文件链接
- 下载方式1:公众号【多栖技术控小董】回复【3674】获取免费下载链接。
- 下载方式2:Github链接https://github.com/dongyusheng/csdn-code/tree/master/Docker/jekyll。进入之后,目录内存储了本文用到的所有文件
二、构建Jekyll容器
①创建目录
- 创建一个jekyll目录,作为本文整体的一个工作目录,然后进入jekyll目录再创建一个jekyll目录,作为构建jekyll的工作路径
mkdir jekyllcd jekyllmkdir jekylllscd 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-27RUN 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.3VOLUME /data
VOLUME /var/www/html
WORKDIR /dataENTRYPOINT [ "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 apachelscd 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-27RUN apt-get -qq update
RUN apt-get -qq install apache2VOLUME [ "/var/www/html" ]
WORKDIR /var/www/htmlENV 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/apache2RUN mkdir -p $APACHE_RUN_DIR $APACHE_LOCK_DIR $APACHE_LOG_DIREXPOSE 80ENTRYPOINT [ "/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 $HOMEgit clone https://github.com/jamtur01/james_blog.gitls 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
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】资料内容。