Files
DefectingCat.github.io/defect/docker-build-own-image.html
DefectingCat 8c7085f18f
2020-11-02 02:17:54 +00:00

128 lines
38 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="zh-CN" data-default-color-scheme="&#34;auto&#34;"><head><meta charset="UTF-8"><link rel="apple-touch-icon" sizes="76x76" href="/images/img/apple-touch-icon.webp"><link rel="icon" type="image/png" href="/images/img/favicon.webp"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,shrink-to-fit=no"><meta http-equiv="x-ua-compatible" content="ie=edge"><meta name="theme-color" content="#9DC8C8"><meta name="description" content=""><meta name="author" content="Defectink"><meta name="keywords" content=""><title>Docker-构建属于自己的镜像 - 🍭Defectink</title><link rel="stylesheet" href="https://cdn.defectink.com/static/twitter-bootstrap/4.5.3/css/bootstrap.min.css"><link rel="stylesheet" href="https://cdn.defectink.com/static/github-markdown-css/4.0.0/github-markdown.min.css"><link rel="stylesheet" href="/lib/hint/hint.min.css"><link rel="stylesheet" href="https://cdn.defectink.com/static/highlight.js/10.0.0/styles/github-gist.min.css"><link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css"><link rel="stylesheet" href="https://cdn.defectink.com/static/t/font_1736178_kmeydafke9r.css"><link rel="stylesheet" href="/css/main.css"><link rel="stylesheet" href="/css/xfy.css"><script src="/js/utils.js"></script><script src="/js/color-schema.js"></script><meta name="generator" content="Hexo 5.2.0"><link rel="alternate" href="/xml/atom.xml" title="🍭Defectink" type="application/atom+xml"><link rel="alternate" href="/xml/rss.xml" title="🍭Defectink" type="application/rss+xml"></head><body><header style="height:75vh"><nav id="navbar" class="navbar fixed-top navbar-expand-lg navbar-dark scrolling-navbar"><div class="container"><a class="navbar-brand" href="/">&nbsp;<strong>🍭Defectink</strong>&nbsp;</a> <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><div class="animated-icon"><span></span><span></span><span></span></div></button><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav ml-auto text-center"><li class="nav-item"><a class="nav-link" href="/">🏠 首页</a></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">📕 索引</a><div class="dropdown-menu" aria-labelledby="navbarDropdown"><a class="dropdown-item" href="/categories/">🎁 分类</a> <a class="dropdown-item" href="/tags/">🎐 标签</a></div></li><li class="nav-item"><a class="nav-link" href="/archives/">📂 归档</a></li><li class="nav-item"><a class="nav-link" href="/about/">🎃 关于</a></li><li class="nav-item"><a class="nav-link" href="/links/">🙆‍♀️ 小伙伴</a></li><li class="nav-item"><a class="nav-link" href="/pgp/">🔐 PGP</a></li><li class="nav-item" id="search-btn"><a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i class="iconfont icon-search"></i>&nbsp;</a></li><li class="nav-item" id="color-toggle-btn"><a class="nav-link" href="javascript:">&nbsp;<i class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a></li></ul></div></div></nav><div class="banner intro-2" id="background" parallax="true" style="background:url(/images/img/post.webp) no-repeat center center;background-size:cover"><div class="full-bg-img"><div class="mask flex-center" style="background-color:rgba(0,0,0,.3)"><div class="container page-header text-center fade-in-up"><span class="h2" id="subtitle"></span><div class="mt-3"><span class="post-meta mr-2"><i class="iconfont icon-author" aria-hidden="true"></i> Defectink</span><span class="post-meta"><i class="iconfont icon-date-fill" aria-hidden="true"></i> <time datetime="2019-11-29 09:30" pubdate>2019年11月29日 上午</time></span></div><div class="mt-1"><span class="post-meta mr-2"><i class="iconfont icon-chart"></i> 4.3k 字</span><span class="post-meta mr-2"><i class="iconfont icon-clock-fill"></i> 54 分钟</span></div></div></div></div></div></header><main><div class="container-fluid"><div class="row"><div class="d-none d-lg-block col-lg-2"></div><div class="col-lg-8 nopadding-md"><div class="container nopadding-md" id="board-ctn"><div class="py-5" id="board"><article class="post-content mx-auto" id="post"><h1 style="display:none">Docker-构建属于自己的镜像</h1><p class="note note-info">本文最后水于2020年11月2日 凌晨</p><div class="markdown-body" id="post-body"><p>以前一直在使用别人构建好的镜像来使用Docker容器在一次想搭建一个完整的Web环境时发现使用过多容器非常难以管理。并且容器之间的交互通信变的困难。当然也可以使用Docker Compose来捆绑多个镜像运行不过对于运行服务较少的来说使用Dockerfile来构建成一个镜像也是件好事。</p><h2 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h2><p>首先在构建一个镜像之前需要先明白这个镜像将会包含哪些东西运行哪些服务。目前主要是想在当前机器上跑一个hexo的blog。当然可以部署在Github以前还写过一篇关于部署在Github的<a href="https://www.defectink.com/defect/set-up-the-hexo-blog.html">水文</a>。不过现在的想法是Github放一份在本地服务器上也跑一个Server。</p><p>当然跑一个hexo是一件很简单的事情使用Docker来部署也是为了想体验一下写<code>Dockerfile</code>。目前有两个思路:</p><ol><li><p>把node.js和hexo都部署在当前的宿主机用Docker的Web服务器来跑宿主机生成的静态文件。</p><blockquote><p>但是这样的话就不需要用到Dockerfile了直接pull一个http服务的镜像就好了。</p></blockquote></li><li><p>只在宿主机上使用Git来和Github同步文件每次的生成和运行Web服务都放在Docker容器里。</p><blockquote><p>目前打算尝试的一种方式可以在每次写完文章后使用Docker构建并且也可以尝试Dockerfile了。</p></blockquote></li></ol><p>具体需要什么使用软件完全看自己的需求需要用到什么就安装什么。就像在当前的宿主机上安装软件一样。只不过是使用Dockerfile来构建时安装的而已。</p><h2 id="构建自己的镜像"><a href="#构建自己的镜像" class="headerlink" title="构建自己的镜像"></a>构建自己的镜像</h2><p>好在还可以使用Dockerfile来基于其他的镜像来构建属于自己的镜像。可以在其他的系统基础镜像上来在构建时就安装自己需要的软件服务等这样就可以构建一个自己需要的镜像了。</p><h3 id="使用基础镜像"><a href="#使用基础镜像" class="headerlink" title="使用基础镜像"></a>使用基础镜像</h3><p>构建时使用的第一个命令是<code>FROM</code>命令。它会指定一个用于构建的基础镜像。这样就可以在基础镜像中使用自己喜欢的发行版,也解决了继承其他 Docker 镜像的途径 。</p><p>创建一个目录,或者<code>clone</code>一个hexo博客等在目录内编写一个<code>Dockerfile</code></p><pre><code class="hljs dockerfile"><span class="hljs-comment">#test</span>
<span class="hljs-keyword">FROM</span> alpine:latest
<span class="hljs-keyword">MAINTAINER</span> Defectink &lt;i@defect.ink&gt;</code></pre><p>这里选择的是alpine系统作为基础镜像主要原因是alpine是个超级轻量的系统对于最为基础镜像可以有效的减少构建后镜像的大小。</p><p>除此之外,还有个<code>MAINTAINER</code>命令它是用来著名当前Dockerfile的作者的。Docker支持<code>#</code>作为注释,使用起来很方便。</p><h3 id="第一次的构建"><a href="#第一次的构建" class="headerlink" title="第一次的构建"></a>第一次的构建</h3><p>编写了一个最基本的<code>Dockerfile</code>之后,就是运行第一次的构建测试了。使用<code>Docker</code>加上<code>build</code>来构建指定的<code>Dockerfile</code>为镜像。添加<code>-t</code>参数来为构建后的镜像指定一个tag标签也就是之后的镜像(REPOSITORY)名。最后命令指定的目录是包含刚刚写好的<code>Dockerfile</code>文件的目录,被称作为“构建目录”。</p><p>当前系统下没有基础镜像alpine的话在第一次运行时docker也会进行下载。</p><pre><code class="hljs bash"><span class="hljs-comment"># docker build -t blog /data/github/DefectingCat.github.io/ </span>
Sending build context to Docker daemon 64kB
Step 1/2 : FROM alpine:latest
latest: Pulling from library/alpine
89d9c30c1d48: Pull complete
Digest: sha256:c19173c5ada610a5989151111163d28a67368362762534d8a8121ce95cf2bd5a
Status: Downloaded newer image <span class="hljs-keyword">for</span> alpine:latest
---&gt; 965ea09ff2eb
Step 2/2 : MAINTAINER Defectink &lt;i@defect.ink&gt;
---&gt; Running <span class="hljs-keyword">in</span> d572ac48c8f8
Removing intermediate container d572ac48c8f8
---&gt; b8296646acaa
Successfully built b8296646acaa
Successfully tagged blog:latest</code></pre><p>第一次的镜像构建已经完成了,虽然什么都没有进行定制,但已经迈出了第一步。</p><h3 id="安装软件"><a href="#安装软件" class="headerlink" title="安装软件"></a>安装软件</h3><p>迈出第一步之后,就可以开始考虑定制属于自己的镜像了。使用<code>docker images</code>可以查看当前系统下的docker镜像。也能看到刚刚所构建的第一个镜像。</p><pre><code class="hljs bash"><span class="hljs-comment"># docker images </span>
REPOSITORY TAG IMAGE ID CREATED SIZE
blog latest b8296646acaa 19 minutes ago 5.55MB
alpine latest 965ea09ff2eb 5 weeks ago 5.55MB</code></pre><p>既然是定制属于自己的镜像那么肯定是需要安装所需求的软件的。这里我想构建一个运行hexo的镜像所以至少需要3款软件</p><ul><li>apache</li><li>node.js</li><li>hexo</li></ul><p>使用<code>RUN</code>命令来在基础镜像上执行命令像是安装软件等操作。由于alpine默认时区不是国内还可以顺便修改下时区。可以使用<code>RUN</code>来一次安装完所有需要的软件,不需要分开执行。</p><p>使用alpine的另个原因就是在它本身体积小的情况下它安装软件还可以使用<code>--no-cache</code>来减少缓存。</p><p>在容器内使用npm来安装hexo时会出现一个<code>uid:0</code>的问题npm会有生命周期某个包会有生命周期来执行一些东西安全起见会自动降级导致没有权限执行一些操作通过``unsafe-perm`参数来解锁该限制。</p><pre><code class="hljs dockerfile"><span class="hljs-comment">#install</span>
<span class="hljs-keyword">RUN</span><span class="bash"> apk update \</span>
<span class="bash"> &amp;&amp; apk upgrade \</span>
<span class="bash"> &amp;&amp; apk add --no-cache \</span>
<span class="bash"> apache2 \</span>
<span class="bash"> nodejs \</span>
<span class="bash"> npm \</span>
<span class="bash"> tzdata \</span>
<span class="bash"> &amp;&amp; cp -r -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span>
<span class="bash"> &amp;&amp; rm -rf /var/cache/apk/* \</span>
<span class="bash"> &amp;&amp; mkdir -p /data/DefectingCat.github.io \</span>
<span class="bash"> &amp;&amp; npm config <span class="hljs-built_in">set</span> unsafe-perm <span class="hljs-literal">true</span> \</span>
<span class="bash"> &amp;&amp; npm install -g hexo</span></code></pre><p>因为是基于一个操作系统上构建的镜像所以在构建完成后可以使用Docker来运行一个“伪终端”让我们可以直接在终端内进行一些修改和查看。值得注意的是在“伪终端”里进行的操作只是在当前容器内的不会被写入镜像。当前被关闭后任何操作将不复存在。</p><p>在构建完后可以使用“伪终端”进入系统内查看一些信息,测试软件能否正常工作等。</p><pre><code class="hljs bash">docker run -it --rm blog</code></pre><p>关于这里的一些参数:</p><ul><li><p><code>-i</code>即使没有附加也保持STDIN 打开。</p></li><li><p><code>-t</code>分配一个伪终端。</p></li><li><p><code>--rm</code>在退出后立刻删除容器。</p></li></ul><h3 id="缓存"><a href="#缓存" class="headerlink" title="缓存"></a>缓存</h3><pre><code class="hljs bash"><span class="hljs-comment"># docker build -t blog /data/github/DefectingCat.github.io/ </span>
Sending build context to Docker daemon 64kB
Step 1/5 : FROM alpine:latest
---&gt; 965ea09ff2eb
Step 2/5 : MAINTAINER Defectink &lt;i@defect.ink&gt;
---&gt; Using cache
---&gt; 92cd04f91315</code></pre><p>在构建的时候可以在某一步(Step)下看到<code>Using cache</code>。 当 Docker 构建镜像时,它不仅仅构建一个单独的镜像;事实上,在构建过程中,它会构建许多镜像。</p><p>输出信息中的每一步(Step)Docker都在创建一个新的镜像。同时它还打印了镜像ID <code>---&gt; 92cd04f91315</code>。这样的好处在于,我们修改<code>Dockerfile</code>后重新构建镜像时,那些没有被修改的部分可以将上次构建的镜像当作缓存,加快构建的速度。</p><p>但是这也会有些小问题Docker是根据<code>Dockerfile</code>来判断构建时的变化的。但如果需要执行更新软件等操作,而<code>Dockerfile</code>内的命令是没有变化时Docker会继续使用以前的缓存导致旧的软件还是被安装了。</p><p>所有在执行某些必要的操作时,不使用缓存也是极有好处的。在构建镜像时,<strong>使用<code>--no-cache=True</code>即可</strong></p><p><code>RUN</code>命令推荐使用一条命令完成尽可能多的操作,<code>Dockerfile</code>中的每个命令都会被分为构建镜像的一步来执行,这样可以减少构建时的步数(Step)。Docker 镜像类似于洋葱。它们都有很多层。为了修改内层,则需要将外面的层都删掉。</p><h3 id="第一次的运行"><a href="#第一次的运行" class="headerlink" title="第一次的运行"></a>第一次的运行</h3><p>将所有的软件都安装、测试完后就可以构建能够第一次运行的镜像了。在此之前还需要配置需要运行的软件例如使用hexo生成静态文件启动apache等。</p><pre><code class="hljs dockerfile"><span class="hljs-keyword">COPY</span><span class="bash"> DefectingCat.github.io /data/DefectingCat.github.io</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /data/DefectingCat.github.io</span>
<span class="hljs-keyword">RUN</span><span class="bash"> hexo g \</span>
<span class="bash"> &amp;&amp; cp -a public/* /var/www/localhost/htdocs</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">80</span> <span class="hljs-number">443</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">&quot;/usr/sbin/httpd&quot;</span>,<span class="hljs-string">&quot;-f&quot;</span>,<span class="hljs-string">&quot;/etc/apache2/httpd.conf&quot;</span>,<span class="hljs-string">&quot;-DFOREGROUND&quot;</span>]</span></code></pre><ul><li><code>COPY</code>将宿主机上的文件复制进容器内的目录。在安装软件时就已经使用<code>RUN</code>来创建过需要的目录了。</li><li><code>WORKDIR</code>切换工作的目录,和<code>cd</code>类似;切换后<code>RUN</code>等命令都会在当前目录下工作。</li><li><code>EXPOSE</code>暴露需要使用到的端口。</li><li><code>CMD</code><code>RUN</code>类似,通常用于来启动容器服务。</li></ul><p>关于<code>CMD</code></p><p><code>CMD</code>只能存在一条,根据运行的软件,它将占据最后容器输出的终端。因为容器并不像虚拟化或者物理机那样,可以使用守护进程;容器本身就是一个进程,容器内没有后台服务的概念。正确的做法是使用<code>CMD</code>直接执行可执行文件,并且要求以前台形式运行。</p><p>当前的操作很简单就是复制宿主机上git克隆下来的文件到容器的制定文件夹然后使用<code>hexo</code>来生成静态文件,最后复制到<code>apache</code>的工作目录下。</p><p>到这里就可以来运行一个一次性的容器测试一下我们的服务是否运行正常了。如果上述都没有任何问题的话现在打开浏览器就应该能看到hexo的blog了🎉。</p><pre><code class="hljs bash">docker run -p 80:80 --rm blog</code></pre><p>到目前为止Dockerfile应该是这样的</p><pre><code class="hljs dockerfile"><span class="hljs-keyword">FROM</span> alpine:latest
<span class="hljs-keyword">MAINTAINER</span> Defectink &lt;i@defect.ink&gt;
<span class="hljs-comment">#install</span>
<span class="hljs-keyword">RUN</span><span class="bash"> apk update \</span>
<span class="bash"> &amp;&amp; apk upgrade \</span>
<span class="bash"> &amp;&amp; apk add --no-cache \</span>
<span class="bash"> apache2 \</span>
<span class="bash"> nodejs \</span>
<span class="bash"> npm \</span>
<span class="bash"> tzdata \</span>
<span class="bash"> &amp;&amp; cp -r -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span>
<span class="bash"> &amp;&amp; rm -rf /var/cache/apk/* \</span>
<span class="bash"> &amp;&amp; mkdir -p /data/DefectingCat.github.io \</span>
<span class="bash"> &amp;&amp; npm config <span class="hljs-built_in">set</span> unsafe-perm <span class="hljs-literal">true</span> \</span>
<span class="bash"> &amp;&amp; npm install -g hexo</span>
<span class="hljs-keyword">COPY</span><span class="bash"> DefectingCat.github.io /data/DefectingCat.github.io</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /data/DefectingCat.github.io</span>
<span class="hljs-keyword">RUN</span><span class="bash"> hexo g \</span>
<span class="bash"> &amp;&amp; cp -a public/* /var/www/localhost/htdocs</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">80</span> <span class="hljs-number">443</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">&quot;/usr/sbin/httpd&quot;</span>,<span class="hljs-string">&quot;-f&quot;</span>,<span class="hljs-string">&quot;/etc/apache2/httpd.conf&quot;</span>,<span class="hljs-string">&quot;-DFOREGROUND&quot;</span>]</span></code></pre><p>安装了一些必要的软件,同时也尽量的减少了镜像构建后的大小。</p><h2 id="HTTPS"><a href="#HTTPS" class="headerlink" title="HTTPS"></a>HTTPS</h2><p>现代的网站应该都不会少的了SSL也就是我们常见的https。目前自己的网站用的是最简单的LetsEncrypt使用他家的工具Certbot来申请证书及其方便。在宿主机的环境下甚至还能自动配置。但是目前用的是Docker环境在使用Dockefile构建时是没有交互环境的。自动配置也可能无法生效。</p><h3 id="生成证书"><a href="#生成证书" class="headerlink" title="生成证书"></a>生成证书</h3><p>Certbot生成证书很是方便在Docker环境下也是如此。使用官方的镜像可以很方便的生成</p><pre><code class="hljs bash">sudo docker run -it --rm --name certbot \
-v <span class="hljs-string">&quot;/etc/letsencrypt:/etc/letsencrypt&quot;</span> \
-v <span class="hljs-string">&quot;/var/lib/letsencrypt:/var/lib/letsencrypt&quot;</span> \
certbot/certbot certonly</code></pre><p>配合<code>certonly</code>只获取证书,并<code>-v</code>来将容器的目录映射到宿主机,这样就能在生成后把证书存到宿主机目录了。</p><p>生成时,也会有两种工作模式选择:</p><pre><code class="hljs bash">How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files <span class="hljs-keyword">in</span> webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] <span class="hljs-keyword">then</span> [enter] (press <span class="hljs-string">&#x27;c&#x27;</span> to cancel):</code></pre><p>分别是:</p><ul><li>standalone模式启动一个临时的webserver</li><li>webroot模式将验证文件放到当前已有的webserver目录下</li></ul><p>如果当前没有正在运行的webserver使用standalone模式是最为方便的。Certbot将自己运行一个临时的webserver完成认证。但是如果使用standalone模式在运行需要添加一个映射的端口</p><pre><code class="hljs bash">sudo docker run -it -p 80:80 --rm --name certbot \
-v <span class="hljs-string">&quot;/data/docker/apache/letsencrypt:/etc/letsencrypt&quot;</span> \
-v <span class="hljs-string">&quot;/var/lib/letsencrypt:/var/lib/letsencrypt&quot;</span> \
certbot/certbot certonly</code></pre><p>因为Certbot启用了一个临时的webserver来验证域名解析如果不把容器的<code>80</code>端口映射出来的话,将无法完成验证。</p><p>在一切都没有任何问题之后就能看到Congratulations了</p><pre><code class="hljs bash">IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/domain/fullchain.pem</code></pre><p>根据官网的说法,证书均链接在<code>/etc/letsencrypt/live</code>目录内。</p><blockquote><p><code>/etc/letsencrypt/archive</code> and <code>/etc/letsencrypt/keys</code> contain all previous keys and certificates, while <code>/etc/letsencrypt/live</code> symlinks to the latest versions.</p></blockquote><h3 id="Mod-ssl"><a href="#Mod-ssl" class="headerlink" title="Mod_ssl"></a>Mod_ssl</h3><p>有了证书之后apache还需要ssl的mod。alpine的镜像安装apache时是没有安装的ssl的mod。所以还需要在Dockerfile内添加一行手动进行安装包名为<code>apache2-ssl</code></p><pre><code class="hljs dockerfile"><span class="hljs-keyword">RUN</span><span class="bash"> apk update \</span>
<span class="bash"> &amp;&amp; apk upgrade \</span>
<span class="bash"> &amp;&amp; apk add --no-cache \</span>
<span class="bash"> apache2 \</span>
<span class="bash"> apache2-ssl \</span></code></pre><p>在重新构建之前还需要修改apache的<code>ssl.conf</code>。如何取得<code>ssl.conf</code>我们只需要构建一个临时的alpine镜像在容器内使用相同的命令安装一个apache与ssl mod之后在<code>/etc/apache2/conf.d</code>目录内就有<code>ssl.conf</code>配置文件了。将其copy到宿主机内修改就好了。</p><pre><code class="hljs bash">apk add apache2-ssl</code></pre><p>在启动命令内的<code>httpd.conf</code>配置文件会包含<code>ssl.conf</code>。所以只需要修改<code>ssl.conf</code>再在构建时将其copy到镜像内就好了。</p><p><code>httpd.conf</code>内的已有配置:</p><pre><code class="hljs awk">IncludeOptional <span class="hljs-regexp">/etc/</span>apache2<span class="hljs-regexp">/conf.d/</span>*.conf</code></pre><p>那么,如何优雅的将容器内的<code>ssl.conf</code>copy出来呢</p><p>可以在先将容器放在后台运行:</p><pre><code class="hljs bash">docker run -id <span class="hljs-built_in">test</span></code></pre><p>然后使用docker自带的<code>docker cp</code>命令来copy到宿主机的目录</p><pre><code class="hljs bash">docker cp 253d3ca34521:/etc/apache2/conf.d/ssl.conf /root</code></pre><p>当然也可以直接打开,然后记录文件内容再复制出来。</p><p>有了Mod_ssl组件之后就可以配合SSL证书来对网站进行加密了。既然能将默认的<code>ssl.conf</code>复制出来,就可以对其修改然后在生成镜像时再复制会容器内的原目录。</p><p>剩下对于SSL的配置就和给宿主机配置加密一样了几乎没有什么不同。主要就是在<code>ssl.conf</code>中填上正确的证书目录:</p><pre><code class="hljs awk">SSLCertificateFile <span class="hljs-regexp">/etc/</span>letsencrypt<span class="hljs-regexp">/live/</span>defect.ink/fullchain.pem
<span class="hljs-comment">#SSLCertificateFile /etc/ssl/apache2/server-dsa.pem</span>
<span class="hljs-comment">#SSLCertificateFile /etc/ssl/apache2/server-ecc.pem</span>
<span class="hljs-comment"># Server Private Key:</span>
<span class="hljs-comment"># If the key is not combined with the certificate, use this</span>
<span class="hljs-comment"># directive to point at the key file. Keep in mind that if</span>
<span class="hljs-comment"># you&#x27;ve both a RSA and a DSA private key you can configure</span>
<span class="hljs-comment"># both in parallel (to also allow the use of DSA ciphers, etc.)</span>
<span class="hljs-comment"># ECC keys, when in use, can also be configured in parallel</span>
SSLCertificateKeyFile <span class="hljs-regexp">/etc/</span>letsencrypt<span class="hljs-regexp">/live/</span>defect.ink/privkey.pem</code></pre><p>Lets Encrypt生成的证书在路径下还会有个<code>fullchain.pem</code>,这是一整个证书链。在配置文件中只需要这个证书和一个私钥<code>privkey.pem</code>就好。</p><h3 id="跳转至443"><a href="#跳转至443" class="headerlink" title="跳转至443"></a>跳转至443</h3><p>在有了https之后如果不需要80端口还能继续访问。可以使用301跳转来将访问80端口的访客都跳转到443。Apache的mod_rewrite可以轻松的实现针对各种条件的跳转。</p><p>mod_rewrite的作用很多能设置的条件也可以很复杂。当然配置个简单的跳转不是非常的复杂。</p><pre><code class="hljs apache"><span class="hljs-attribute"><span class="hljs-nomarkup">RewriteEngine</span></span> <span class="hljs-literal">on</span>
<span class="hljs-attribute"><span class="hljs-nomarkup">RewriteCond</span></span> <span class="hljs-variable">%&#123;SERVER_NAME&#125;</span> =defect.ink
<span class="hljs-attribute"><span class="hljs-nomarkup">RewriteRule</span></span> ^ https://<span class="hljs-variable">%&#123;SERVER_NAME&#125;</span><span class="hljs-variable">%&#123;REQUEST_URI&#125;</span><span class="hljs-meta"> [END,NE,R=permanent]</span></code></pre><ul><li><code>RewriteEngine</code>打开跳转引擎;</li><li><code>RewriteCond</code>跳转的条件;这里设置当域名为<code>defect.ink</code>时,执行下面的跳转动作;</li><li><code>RewriteRule</code>跳转的动作当符合上面的条件时执行添加https<code>https://%&#123;SERVER_NAME&#125;%&#123;REQUEST_URI&#125;</code>。而后面的变量保持不动。</li></ul><p>这行配置是来自于certbot的自动配置中的在配置宿主机的ssl时可以选择全部跳转。然后它就会帮我们自动配置了。对其进行简单的修改就可以作用与其他的配置文件了。</p><p>这几行推荐是写在<code>httpd.conf</code>的末尾,也就是<code>IncludeOptional /etc/apache2/conf.d/*.conf</code>的上方。虽然ssl.conf也会被include进来但是还是感觉写在这里要方便一点。</p><p>然后将<code>httpd.conf</code><code>ssl.conf</code>一样在构建时复制到容器内就ok了。</p><pre><code class="hljs dockerfile">&amp;&amp; cp -a ssl.conf /etc/apache2/conf.d/ \
&amp;&amp; cp -a httpd.conf /etc/apache2/</code></pre><h3 id="Renew"><a href="#Renew" class="headerlink" title="Renew"></a>Renew</h3><p>Lets Encrypt的证书虽然很方便但是一次只能生成三个月有效期的证书。使用和生成差不多的方法renew证书就好了。</p><pre><code class="hljs livescript">sudo docker run -<span class="hljs-literal">it</span> -p <span class="hljs-number">80</span>:<span class="hljs-number">80</span> --rm --name certbot <span class="hljs-string">\</span>
-v <span class="hljs-string">&quot;/data/docker/apache/letsencrypt:/etc/letsencrypt&quot;</span> <span class="hljs-string">\</span>
-v <span class="hljs-string">&quot;/var/lib/letsencrypt:/var/lib/letsencrypt&quot;</span> <span class="hljs-string">\</span>
certbot/certbot renew</code></pre><p>想要自动化执行话可以使用crontab来定时运行。</p><h2 id="全部的Dockerfile"><a href="#全部的Dockerfile" class="headerlink" title="全部的Dockerfile"></a>全部的Dockerfile</h2><p>这时候的配置文件看起来应该是这个样子的:</p><pre><code class="hljs dockerfile"><span class="hljs-comment">#test</span>
<span class="hljs-keyword">FROM</span> alpine:latest
<span class="hljs-keyword">MAINTAINER</span> Defectink &lt;i@defect.ink&gt;
<span class="hljs-comment">#install</span>
<span class="hljs-keyword">RUN</span><span class="bash"> apk update \</span>
<span class="bash"> &amp;&amp; apk upgrade \</span>
<span class="bash"> &amp;&amp; apk add --no-cache \</span>
<span class="bash"> apache2 \</span>
<span class="bash"> apache2-ssl \</span>
<span class="bash"> nodejs \</span>
<span class="bash"> npm \</span>
<span class="bash"> tzdata \</span>
<span class="bash"> &amp;&amp; cp -r -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span>
<span class="bash"> &amp;&amp; rm -rf /var/cache/apk/* \</span>
<span class="bash"> &amp;&amp; mkdir -p /data/DefectingCat.github.io \</span>
<span class="bash"> &amp;&amp; npm config <span class="hljs-built_in">set</span> unsafe-perm <span class="hljs-literal">true</span> \</span>
<span class="bash"> &amp;&amp; npm install -g hexo</span>
<span class="hljs-keyword">COPY</span><span class="bash"> DefectingCat.github.io /data/DefectingCat.github.io</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /data/DefectingCat.github.io</span>
<span class="hljs-keyword">RUN</span><span class="bash"> hexo g \</span>
<span class="bash"> &amp;&amp; cp -a public/* /var/www/localhost/htdocs/ \</span>
<span class="bash"> &amp;&amp; cp -a ssl.conf /etc/apache2/conf.d/ \</span>
<span class="bash"> &amp;&amp; cp -a httpd.conf /etc/apache2/</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">80</span> <span class="hljs-number">443</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">&quot;/usr/sbin/httpd&quot;</span>,<span class="hljs-string">&quot;-f&quot;</span>,<span class="hljs-string">&quot;/etc/apache2/httpd.conf&quot;</span>,<span class="hljs-string">&quot;-DFOREGROUND&quot;</span>]</span></code></pre><h2 id="启动!"><a href="#启动!" class="headerlink" title="启动!"></a>启动!</h2><pre><code class="hljs bash">docker run -id --name=<span class="hljs-string">&quot;blog&quot;</span> -v /etc/letsencrypt/:/etc/letsencrypt/ -p 80:80 -p 443:443 blog</code></pre><p>全部操作完了,启动命令也随着操作变得更加的复杂了。</p><ul><li><code>-id</code>扔到后台;</li><li><code>--name</code>容器别名;</li><li><code>-v</code>映射之前的ssl证书的目录</li><li><code>-p</code>80和443都需要映射</li></ul><h2 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h2><p>一些比较方便的命令。</p><p>删除所有<code>&lt;none&gt;</code>的镜像:</p><pre><code class="hljs bash">docker rmi $(docker images -f <span class="hljs-string">&quot;dangling=true&quot;</span> -q)</code></pre><p>停止所有容器,删除所有容器:</p><pre><code class="hljs bash">docker <span class="hljs-built_in">kill</span> $(docker ps -q) ; docker rm $(docker ps -a -q)</code></pre><p>停止所有容器,删除所有容器,<strong>删除所有镜像</strong></p><pre><code class="hljs bash">docker <span class="hljs-built_in">kill</span> $(docker ps -q) ; docker rm $(docker ps -a -q) ; docker rmi $(docker images -q -a)</code></pre><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><p><a target="_blank" rel="noopener" href="https://www.digitalocean.com/community/tutorials/how-to-create-an-ssl-certificate-on-apache-for-centos-7">How To Create an SSL Certificate on Apache for CentOS 7</a></p></li><li><p><a target="_blank" rel="noopener" href="https://pkgs.alpinelinux.org/package/edge/main/x86/apache2-ssl">apache2-ssl</a></p></li><li><p><a target="_blank" rel="noopener" href="https://certbot.eff.org/docs/install.html#running-with-docker">Certbot running with Docker</a></p></li><li><p><a target="_blank" rel="noopener" href="https://certbot.eff.org/docs/using.html#where-certs">Where my Certificate</a></p></li></ul></div><hr><div><div class="post-metas mb-3"><div class="post-meta mr-3"><i class="iconfont icon-category"></i> <a class="hover-with-bg" href="/categories/%E5%AE%9E%E8%B7%B5/">实践</a></div><div class="post-meta"><i class="iconfont icon-tags"></i> <a class="hover-with-bg" href="/tags/Linux/">Linux</a></div></div><p class="note note-warning"><a target="_blank" href="https://zh.wikipedia.org/wiki/Wikipedia:CC_BY-SA_3.0%E5%8D%8F%E8%AE%AE%E6%96%87%E6%9C%AC" rel="nofollow noopener noopener">CC BY-SA 3.0❤</a></p><div class="post-prevnext row"><article class="post-prev col-6"><a href="/defect/header-practice-have-to-win-this-a.html"><i class="iconfont icon-arrowleft"></i> <span class="hidden-mobile">Header实践-得拿下这个A</span> <span class="visible-mobile">上一篇</span></a></article><article class="post-next col-6"><a href="/defect/modify-icloud-storage-location-on-windows.html"><span class="hidden-mobile">修改Windows端iCloud云盘存储位置</span> <span class="visible-mobile">下一篇</span><i class="iconfont icon-arrowright"></i></a></article></div></div><article class="comments" id="comments"><div id="vcomments"></div><script type="text/javascript">function loadValine(){addScript("https://cdn.defectink.com/static/valine/1.4.14/Valine.min.js",function(){new Valine({el:"#vcomments",app_id:"dD9t7mcIBVzJWag5ez6GPy2v-MdYXbMMI",app_key:"bWG6pmKsEscrH4JjrpNNAAy6",placeholder:"嘤嘤嘤???",path:window.location.pathname,avatar:"retro",meta:["nick","mail","link"],pageSize:"10",lang:"zh-CN",highlight:!0,recordIP:!1,serverURLs:""})})}waitElementVisible("vcomments",loadValine)</script><noscript>Please enable JavaScript to view the <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments powered by Valine.</a></noscript></article></article></div></div></div><div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn"><div id="toc"><p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p><div id="tocbot"></div></div></div></div></div></main><a id="scroll-top-button" href="#" role="button"><i class="iconfont icon-arrowup" aria-hidden="true"></i></a><div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true"><div class="modal-dialog modal-dialog-scrollable modal-lg" role="document"><div class="modal-content"><div class="modal-header text-center"><h4 class="modal-title w-100 font-weight-bold">搜索</h4><button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button></div><div class="modal-body mx-3"><div class="md-form mb-5"><input type="text" id="local-search-input" class="form-control validate"> <label data-error="x" data-success="v" for="local-search-input">关键词</label></div><div class="list-group" id="local-search-result"></div></div></div></div></div><footer class="text-center mt-5 py-3"><div class="footer-content"><a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a><i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a></div><div class="beian"><a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">皖ICP备17017808号</a></div></footer><script src="https://cdn.defectink.com/static/jquery/3.4.1/jquery.min.js"></script><script src="https://cdn.defectink.com/static/twitter-bootstrap/4.5.3/js/bootstrap.min.js"></script><script src="/js/debouncer.js"></script><script src="/js/main.js"></script><script src="/js/lazyload.js"></script><script defer="defer" src="https://cdn.defectink.com/static/clipboard.js/2.0.6/clipboard.min.js"></script><script src="/js/clipboard-use.js"></script><script src="/js/xfy.js"></script><script src="https://cdn.defectink.com/static/tocbot/4.11.1/tocbot.min.js"></script><script>$(document).ready(function(){var t=$("#board-ctn").offset().top;tocbot.init({tocSelector:"#tocbot",contentSelector:"#post-body",headingSelector:"h1,h2,h3,h4,h5,h6",linkClass:"tocbot-link",activeLinkClass:"tocbot-active-link",listClass:"tocbot-list",isCollapsedClass:"tocbot-is-collapsed",collapsibleClass:"tocbot-is-collapsible",collapseDepth:3,scrollSmooth:!0,headingsOffset:-t}),0<$(".toc-list-item").length&&$("#toc").css("visibility","visible")})</script><script src="https://cdn.defectink.com/static/typed.js/2.0.11/typed.min.js"></script><script>var typed=new Typed("#subtitle",{strings:[" ","Docker-构建属于自己的镜像&nbsp;"],cursorChar:"❤",typeSpeed:70,loop:!1});typed.stop(),$(document).ready(function(){$(".typed-cursor").addClass("h2"),typed.start()})</script><script src="/js/local-search.js"></script><script>var path="/xml/local-search.xml",inputArea=document.querySelector("#local-search-input");inputArea.onclick=function(){searchFunc(path,"local-search-input","local-search-result"),this.onclick=null}</script><script src="https://cdn.defectink.com/static/fancybox/3.5.7/jquery.fancybox.min.js"></script><link rel="stylesheet" href="https://cdn.defectink.com/static/fancybox/3.5.7/jquery.fancybox.min.css"><script>$("#post img:not(.no-zoom img, img[no-zoom]), img[zoom]").each(function(){var t=document.createElement("a");$(t).attr("data-fancybox","images"),$(t).attr("href",$(this).attr("src")),$(this).wrap(t)})</script><script src="https://cdn.defectink.com/static/mermaid/8.5.0/mermaid.min.js"></script><script>window.mermaid&&mermaid.initialize({theme:"default"})</script></body></html>