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
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
$ 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帳號
- 登入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, 不會改變下個指令的當前目錄位置
- 常見的指令有
-
FROM、MAINTAINER、RUN、ADD、EXPOSE、ENV、VOLUME、CMD、ENTRYPOINT
- 官方文件
Dockerfile
-
第一個instruction一定是FROM
-
用來指定base image,還記得一開始使用的base image是哪個嗎?
- 通常第二個是MAINTAINER
-
設定image的author
- RUN
- 用來跑shell指令
- EXPOSE
- expose 8080 port的資訊
- CMD
- container啟動時預設要執行的指令或參數,可被複寫
Sample Dockerfile
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