Using Docker to Build Java Web Dev Environments


Study Hsueh

2014/07/19

Java RAD Study Group Meeting #5

What is Docker?

  • Docker is a container engine


  • What is Container?
    • Container只是一群放在Linux Box裡面的processes, 這些processes是在一個隔離的環境下執行。此外,Container之間是彼此看不到對方的。
      • 在Box裡面, Container看起來像是VM
      • 在Box外面, Container就跟一般process沒什麼兩樣

    • Container不像VM需要模擬硬體, 因此在速度上會比VM快
      • 由於沒有模擬硬體, 所以目前也不能拿來跑Windows or OS X

Docker is based on Some Linux features

  • namespaces
    • 讓每個container可以有自己的pid, net, ipc...
    • 就像Java可以在不同的package下, 有著相同名稱的class
  • cgroup (control group)
    • 控制process的resources, 像是memory, CPU之類的...
    • 可以想像成process版的ulimit (user limits)
  • UnionFS
    • 以Layer的概念來疊出File System





Don't be afraid!

The Underlying Technologies of Docker are not something new

Thinking IN Docker

  • 當你要部署程式在不同平台
  • 當你的Development環境與Production環境不同
  • 當你在雲端要搬家
  • 當你的VM hypervisor資源很吃緊
  • 當你想要快速得知CI結果時
  • ....

來~自己想一個

A Vagrantfile to spin up a Docker-Ready AWS Instance



https://gist.github.com/phstudy/9a213975471dcb4751b2


  • If you forget how to use Vagrant, you can see this slide.


  • Security Group
    • 請開22, 8080跟9000 tcp port

STEP BY STEP

設定Vagrantfile
$ mkdir ~/ec2_docker && cd ~/ec2_docker
$ wget -O Vagrantfile http://goo.gl/D5jtwQ #填入需要的資料
$ vagrant up --provider=aws
#啟動EC2 instance
$ vagrant ssh
  # 透過vagrant登入ec2 instance


在AWS instance裡面查詢目前public ip
$ curl http://169.254.169.254/latest/meta-data/public-ipv4

check your docker environment

  • 檢查docker daemon、docker client、git與go版本
    $ sudo docker version

Some basic docker commands

  • 開始一個新的container

    $ sudo docker run -i -t ubuntu:14.04 /bin/bash


  • 指令分解
    • docker run:        啟動一個新的container
    • -i -t:                          互動模式 (不精准的說法)
    • ubuntu:14.04: 使用ubuntu base image來建立container, 14.04是tag. 若本地端沒有ubuntu的image, 會從Docker Hub Registry上拉下來。
    • /bin/bash:           container開啟後, 執行/bin/bash


Container啟動後

  • Container啟動成功後,應該會看到下面的畫面
    •  1b51164303a9是container id
  • 當你看到上面的畫面時,代表已經進入container(在Linux Box裡面),四處看看吧,看是不是很像VM呢?


  • 接著輸入exit, 停止container


查詢container狀態

$ sudo docker ps -a


  • 指令分解:
    • docker ps: 查詢container資訊
    • -a:                   查詢所有container, 包含已經停止的container, 若不加-a參數,只會查到running狀態的container。

重新啟動container

$ sudo docker start -i 1b51164303a9




注意:

  • 重新開關container時,記憶體裡面的資料都會不見,例如你export某個變數,重啟後會不見。 (據說之後會增加這方面的功能)
  • 若是檔案的異動,則不受影響 (這要歸功於UnionFS)


Docker Hub Registry

  • Docker hub registry是Docker官方提供的Docker Image Repository

  • 搜尋Image
    $ sudo docker search <IMAGE_NAME>

  • 下載Image
    $ sudo docker pull <REPOSITORY>

Install DockerUI

來裝個Docker Web UI界面吧,安裝指令:

  • 安裝git
    $ sudo yum  install git-core
  • 建立DockerUI Image
    $ sudo docker build -t crosbymichael/dockerui github.com/crosbymichael/dockerui

  • 啟動DockerUI Container, 並把port 9000映射到本機上
    $ sudo docker run -d -p 9000:9000 -v /var/run/docker.sock:/docker.sock crosbymichael/dockerui -e /docker.sock
    • -d:  代表detach (在背景執行)

  • 開網頁看9000 port吧
設定完成的畫面




Warnning


Do NOT expose Docker Web UI to PUBLIC

Build A Java WEb ready image

  • 我們延用第一次建立的container
    $ sudo docker start -i e314e51784f4

  • 進入container後,先更新repo資料,接著安裝tomcat 7
    $ apt-get update
    $ apt-get install tomcat7


  • 完成後離開container
    $ exit

Build A Java WEb ready image

  • 用安裝好tomcat的container來建立image
    $ sudo docker commit -a "Study Hsueh <ph.study@gmail.com>"  -m "My Java Web Image"  1b51164303a9   phstudy/my-java-web:0.1

  • 指令分解
    • docker commit:     把修改過的container狀態存到image
    • -a:                                    image的作者資訊
    • -m:                                  image的Commit message
    • 1b51164303a9:  container id
    • phstudy/my-java-web:0.1:  image的名稱與tag, image的名稱包含了username, 記得改成你自己的username

Build A Java WEb ready image

  • 來查看看剛建立的image資訊,查詢image指令如下:
    $ sudo docker images
    • 你也可以用先前裝的DockerUI查唷 :)


  • 用新建立的image啟動一個新的container
    $ sudo docker run -d -p 8080:8080 phstudy/my-java-web:0.1 /bin/bash -c 'service tomcat7 start || tail -f /var/log/tomcat7/catalina.out'

    ps. 畫面會提示啟動fail
    可以不必理會,是ubuntu官方tomcat7的問題

  • 停止Container
    $ sudo docker stop <container_id>

Push your Image to Docker Hub Registry


  • 登入Docker Hub Registry
    $ sudo docker login


  • Push  image to docker hub registry
    $ sudo docker push "phstudy/my-java-web:0.1"






恭喜~
你已經建立人生中的第二個Docker Image




但是...

如果哪天tomcat 7 想要升級成 tomcat8

這些操作不就都要重來一次呢!?





是否有其他好方法呢?






用Dockerfile吧!!!

Dockerfile

  • Dockerfile是由一系列的instructions組成的
  • Instruction
    • 不分大小寫、但通常會用大寫來與一般指令做區隔
    • 每一個指令都是獨立的
      • 例如RUN cd /home, 不會改變下個指令的當前目錄位置
    • 常見的指令有
      • FROMMAINTAINERRUNADDEXPOSEENVVOLUMECMDENTRYPOINT

  • 官方文件

Dockerfile

  • 第一個instruction一定是FROM
    • 用來指定base image,還記得一開始使用的base image是哪個嗎?

  • 通常第二個是MAINTAINER
    • 設定image的author
  • RUN
    • 用來跑shell指令
  • EXPOSE
    • expose 8080 port的資訊
  • CMD
    • container啟動時預設要執行的指令或參數,可被複寫

Sample Dockerfile





https://gist.github.com/phstudy/c79efbfda9f10e6c2960

step by step

  • 建立專案的資料夾
    $ mkdir ~/myTomcat && cd ~/myTomcat

  • 下載Sample Dockerfile
    $ wget -O Dockerfile http://goo.gl/WHax5X

  • 用Dockerfile建立image
    $ sudo docker build -t "phstudy/my-java-web-dockerfile:0.1" .

  • 啟動container
    $ sudo docker run -d -p 8080:8080  phstudy/my-java-web-dockerfile:0.1

  • 關閉container
    $ sudo docker stop  <container_id>

掛載Volume

  • Ubuntu的Tomcat預設ROOT webapp的路徑是/var/lib/tomcat7/webapps/ROOT/


  • 讓我們試著把host的某個目錄, 掛載到container中ROOT webapp的目錄
    $ mkdir ~/ROOT && cd ~/ROOT
    $ echo 'hello world' > hello.jsp

    $ sudo docker run -d -p 8080:8080   -v  ~/ROOT/:/var/lib/tomcat7/webapps/ROOT/ phstudy/my-java-web-dockerfile:0.1

  • 完成
    瀏覽http://YOU_EC2_IP:8080/hello.jsp






The End

Using Docker to Build Java Web Dev Environments

By study

Using Docker to Build Java Web Dev Environments

  • 1,069