docker實戰——構建Jekyll


構建第一個應用

要構建的第一個應用是Jekyll框架的自定義網站。我們會構建一下兩個鏡像。

  • 一個鏡像安裝Jekyll以及其他用於構建Jekyll網站的必要的軟件包。
  • 一個鏡像通過Apache來讓Jekyll網站工作起來。

在啟動容器時,通過創建一個新的Jekyll網站來實現自服務。工作流程如下:

  • 創建Jekyll基礎鏡像和Apache鏡像(只需要構建一次)。
  • 從Jekyll鏡像創建一個容器,這個容器存放通過卷掛載的網址源代碼。
  • 從Apache鏡像創建一個容器,這個容器利用包含編譯后的網站的卷,並為其服務。
  • 在網站需要更新時,清理並重復上面的步驟。

可以把這個例子看做是創建一個多主機站點最簡單的方法。

構建Jekyll鏡像

創建Dockerfile:

# mkdir /opt/jekyll
# cd /opt/jekyll
# vim Dockerfile

FROM ubuntu:latest
MAINTAINER Bourbon Tian "bourbon@1mcloud.com"
ENV REFRESHED_AT 2017-06-13

RUN apt-get -qq update
RUN apt-get -qq install ruby ruby-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" ]

鏡像基於Ubuntu:latest,並且安裝ruby和用於支持Jekyll的包。然后通過VOLUME指令創建了以下兩個卷。

  • /data 用來存放網站的源代碼
  • /var/www/html 用來存放編譯后的Jekyll網站碼

然后將工作目錄設置到/data/,並通過ENTRYPOINT指令指定自動構建的命令,這個命令會將工作目錄/data/中所有的Jekyll網站代碼構建到/var/www/html/目錄中。

構建Jekyll基礎鏡像

通過Dockerfile,可以使用docker build命令構建出可以啟動容器的鏡像。

# docker build -t test/jekyll .
Sending build context to Docker daemon 1.691 MB
Sending build context to Docker daemon 
Step 0 : FROM ubuntu:latest
 ---> db12a182ded0
Step 1 : MAINTAINER Bourbon Tian "bourbon@1mcloud.com"
 ---> 6c517b49846f
...
Successfully built c8ea1e6c398b

這里就構建了一個名為test/jekyll、ID為c8ea1e6c398b的新鏡像。我們可以通過docker images命令來查看:

# docker images
REPOSITORY                                TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
test/jekyll                               latest              c8ea1e6c398b        About an hour ago   455.3 MB

構建Apache鏡像

創建Dockerfile:

# mkdir /opt/apache
# cd /opt/apache
# vim Dockerfile

FROM ubuntu:latest
MAINTAINER Bourbon Tian "bourbon@1mcloud.com"
ENV REFRESHED_AT 2017-06-13

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/apache2" ]
CMD ["-D", "FOREGROUND"]

這個鏡像也是基於Ubuntu:latest,並且安裝了Apache。然后使用VOLUME指令創建了一個卷,即/var/www/html/,用來存放編譯后的Jekyll網站。然后將/var/www/html設為工作目錄。

使用ENV指令設置了一些必要的環境變量,創建了必要的目錄,並且使用EXPOSE公開了80端口。最后指定了ENTRYPOINT和CMD指令組合賴在容器啟動時默認運行Apache。

構建Apache鏡像

# docker build -t test/apache .
Sending build context to Docker daemon  2.56 kB
Sending build context to Docker daemon 
Step 0 : FROM ubuntu:latest
 ---> db12a182ded0
...
Successfully built f97bb19ef81c

這里構建了一個名為test/apache、ID為f97bb19ef81c的新鏡像。可以通過docker images查看:

# docker images
REPOSITORY                                TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
test/apache                               latest              f97bb19ef81c        About an hour ago   255.2 MB

啟動Jekyll網站

現在有了以下兩個鏡像。

  • Jekyll:安裝了Ruby及其他必備軟件包的Jekyll鏡像。
  • Apache:通過Apache Web服務器來讓Jekyll網站工作起來的鏡像。

我們從使用docker run命令來創建一個新的Jekyll容器開始我們的網站。我們將啟動容器,並構建我們的網站。我們將啟動容器,並構建我們的網站。

# cd /opt/jekyll
# git clone https://github.com/turnbullpress/james_blog.git
# docker run -v /opt/jekyll/james_blog:/data/ --name james_blog test/jekyll
Configuration file: /data/_config.yml
            Source: /data
       Destination: /var/www/html
      Generating... 
                    done.

這里啟動了一個叫james_blog的新容器,把本地的james_blog目錄作為/data/卷掛載到容器里。容器已經拿到網站的源代碼,並將其構建到已編譯的網站,存放到/var/www/html/目錄。

卷是在一個或多個容器中特殊指定的目錄,卷會繞過聯合文件系統,為持久化數據提和共享數據提供幾個有用的特性:

  • 卷可以在容器間共享和重用。
  • 共享卷時不一定要運行相應的容器。
  • 對卷的修改會直接在卷上反映出來。
  • 更新鏡像時不會包含對卷的修改。
  • 卷會一直存在,直到沒有容器使用它們。

利用卷,可以在不用提交鏡像修改的情況下,向鏡像里加入數據(如源代碼、數據或者其他內容),並且可以在容器間共享這些數據。卷在Docker宿主機的/var/lib/docker/volumes目錄中。可以通過docker inspect命令查看某個卷的具體位置。

# docker inspect -f "{{ .Volumes}}" james_blog
map[/data:/opt/jekyll/james_blog /var/www/html:/var/lib/docker/volumes/6bf6fbf5ef4017c7aaab6f681b396f32f0f3878a3958f833e02973e0826ccafd/_data]

 如果想在另一個容器里使用/var/www/html/卷里編譯好的網站,可以創建一個新的連接到這個卷的容器:

# docker run -d -P --volumes-from james_blog test/apache
  • --volumes-from把指定容器里的所有卷都加入新創建的容器里。

這意味着,Apache容器可以訪問之前創建的james_blog容器里/var/www/html卷中存放的編譯后的Jekyll網站。即便james_blog容器沒有運行,Apache容器也可以訪問這個卷。

不過,容器本身必須存在。如果用docker rm命令刪除了james_blog容器,那么這個卷和卷里的內容也就不存在了。

現在在宿主機上瀏覽該網站,首先查看容器公開的80端口映射到了宿主機的哪個端口:

# docker port f39825fd8f61 80
0.0.0.0:32782

更新Jekyll網站

如果需要更新網站的數據,假設要修改Jekyll網站的博客名字,我們只需要通過編輯宿主機上 james_blog/_config.yml文件

# pwd
/opt/jekyll/james_blog

# vi _config.yml

 並將title域改為Bourbon Blog。

然后通過使用docker start命令啟動Docker容器即可:

# docker start james_blog
james_blog

## 看上去什么都沒有發生。我們來查看一下日志
# docker logs james_blog
Configuration file: /data/_config.yml
            Source: /data
       Destination: /var/www/html
      Generating... 
                    done.
 Auto-regeneration: disabled. Use --watch to enable.
Configuration file: /data/_config.yml
            Source: /data
       Destination: /var/www/html
      Generating... 
                    done.
 Auto-regeneration: disabled. Use --watch to enable.

 可以看到,Jekyll編譯過程第二次被運行,並且往網站已經被更新。這次更新已經寫入了對應的卷。現在瀏覽Jekyll網站,就能看到變化了。

 

由於共享的卷會自動更新,這一切都不要更新或者重啟Apache容器。這個流程非常簡單,可以將其擴展到更復雜的部署環境。

備份Jekyll卷

如果擔心一不小心刪除卷。由於卷的優點之一就是可以掛載到任意的容器,因此可以輕松備份它們。現在創建一個新容器,用來備份/var/www/html卷

# docker run --rm --volumes-from james_blog -v $(pwd):/backup ubuntu tar cvf /backup/james_blog_backup.tar /var/www/html
tar: Removing leading `/' from member names
/var/www/html/
/var/www/html/History.markdown
/var/www/html/atom.xml
/var/www/html/pages.html
...

# ls james_blog_backup.tar 
james_blog_backup.tar

這里我們運行了一個已有的Ubuntu容器,並把james_blog的卷掛載到該容器。這會在該容器里創建/var/www/html目錄。然后我們使用一個-v標志把當前目錄(通過$(pwd)命令獲得)掛載到容器的/backup 目錄。最后我們的容器運行這一備份命令。

  • --rm 標志,這個標志對於只用一次的容器,或者說用完即扔的容器,很有用。這個標志在容器的進程運行完畢后,自動刪除容器。對於只用一次的容器來說,這是一種很方便的清理方法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM