手把手docker部署java應用(初級篇)

本篇原創發佈於 Flex 的我的博客:點擊跳轉java

前言

  在沒有 docker 前,項目轉測試是比較麻煩的一件事。首先會化較長的時間搭建測試環境,而後在測試過程當中又常常出現測試說是 bug,開發說沒法復現的狀況,致使撕逼。mysql

  本篇記錄瞭如何將一個 java 應用部署到 docker 中。主要講述瞭如下幾個部分:linux

  • docker 部署 mysql
  • docker 部署 activemq
  • docker 部署 elastricsearch 集羣
  • docker 部署 java 應用
  • docker 部署 nginx 做爲靜態服務器,及代理服務器

項目架構以下:nginx

項目架構

本系統中有三個主要模塊 OMS,DAS 和一個 Eureka 註冊中心。其中 OMS 和 DAS 使用有 activemq 消息隊列,來進行大量數據的交互而後各自使用一個 mysql 數據庫存儲主要的業務數據。使用 elastricsearch 存儲超大量的數據。sql

傳統軟件部署和 docker 部署

  本項目在 windows 部署時是將其做爲三個部分來進行安裝的--ENV 環境包(保護 mysql,es 等),OMS 產品包,DAS 產品包。因此最初個人設想是一個容器中裝 ENV 環境包所需的全部軟件,一個容器裝 DAS,一個容器裝 OMS。而後再實踐的過程當中愈來愈感受不對勁,環境配置比較複雜,並且也有種把容器當虛擬機用的感受,一點沒有簡化的感受。docker

  遂停下了操做,開始學習一波 docker 究竟是怎麼用的。用租房子來作比喻:數據庫

  • 傳統軟件部署方式至關於租到一個零傢俱,零裝修的房子。咱們想要住進去首先必須買齊必要的傢俱,而後想要住的舒心呢,還得花功夫裝飾裝飾,讓房子好看點。這樣就會對這個具體的房子產生較強的依賴,很難遷移到另外一個房子中(想一想那麼多的傢俱,家電,雜物。。)。若是所有放棄從新換一個房子代價又太大了。

搬家

  • 使用 docker 至關於租到一個全家電,精裝修的房子。咱們只需帶上本身的我的物品便可開始入住。想要換一個房子也是垂手可得,帶上本身的東西麻溜的就換了。

輕鬆搬家

  使用 docker 推薦操做是一個進程放到一個容器中,作到更好的隔離性,同時也更容易進行管理。下面來使用容器技術部署咱們應用。仍是分爲三部分,可是每一個進程使用一個容器,作到 0 配置啓動容器。ubuntu

實戰

  在此默認已經會安裝 docker,且瞭解基本操做。如不瞭解的先看這兩篇:安裝基本使用windows

部署 ENV 環境包

  環境包中諸如 elastricsearch,mysql 這樣的數據存儲工具,須要知足以下兩個要求:tomcat

  1. 保留數據,不論容器如何建立、銷燬,數據不能丟。
  2. 須要使用個性化的配置文件,每次啓動根據該配置文件來啓動。

部署 mysql

  使用容器部署 mysql 過程以下:

  1. 首先從 docker.hub 中根據各自的需求 pull 對應的 mysql 鏡像
docker pull mysql:5.7.24
  1. 啓動鏡像

  因爲 mysql 是用來存數據的,數據不管什麼狀況都不能丟失,因此數據存在容器外部,經過映射操做,映射到容器內部,參數以下:

# 將宿主機的路徑,映射到容器內部。這個路徑既能夠是文件夾,也能夠是文件
-v hostPath:containerPath

顯然咱們經過這個桉樹將外部的數據文件夾,配置文件映射到容器中。最後啓動這個容器的命令以下:

# 假設在宿主機中數據存放路徑爲/opt/mysql/data,配置文件路徑爲:/opt/mysql/my.cnf
docker run --name=mysql -itd -p 3308:3306 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -v /opt/mysql/data:/var/lib/mysql -v /opt/mysql/my.cnf:/etc/mysql/my.cnf -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.25

注意:若是 mysql 版本爲 8.x,還須要映射容器中的/var/lib/mysql-files 目錄,不然啓動會報錯

下面介紹具體參數含義:

  • -it 標準輸入輸出有關
  • -d 後臺啓動
  • -v 文件映射
  • -e 設置環境變量到容器中

  可能大家會問爲何要映射/etc/timezone/etc/timezone,這是爲了讓容器的時間和時區與宿主機保持一致。默認狀況下容器爲 UTC 標準時間。/etc/timezone讓容器時間,時區和宿主機一致。可是若是不映射/etc/timezonejava 應用中的時區仍是錯的,雖然使用date -R命令查看時間和時區都正常。

部署 elastricsearch,activeMQ 容器

  es 和 activeMQ 都依賴 java 的運行環境,因此有兩種部署方式:

  • 直接拉取 es,activeMQ 對應鏡像,經過路徑映射部署容器啓動
  • 在一個 java 鏡像中運行 es 和 activeMQ

  這裏以第二種方式爲例進行說明。

建立 java 鏡像

  這裏不從 docker hub 中拉取鏡像,經過 dockerfile 來製做一個自定義的鏡像。因爲只須要一個 java 運行環境,因此只要將一個 jre 運行環境加入到一個基礎 linux 鏡像中便可(這裏選擇 ubuntu)。製做過程以下:

  首先建立一個文件夾dockerFileTest存放依賴和 dockerfile 文件。

  而後將下載加壓後的 jre 運行環境放到dockerFileTest/jre目錄下。

  接着在 dockerFileTest 目錄中建立 Dockerfile 文件,內容以下:

#說明基礎鏡像,默認:latest
FROM ubuntu
#將當前路徑下的jre文件夾複製到新鏡像下的/opt/jre路徑
COPY jre /opt/jre
#設置環境變量
ENV JAVA_HOME=/opt/jre CLASSPATH=/opt/jre/lib PATH=$PATH:/opt/jre/bin

  最後經過``命令生成新鏡像 jre:v1

建立 elastricsearch 容器

  下載好 es,假設存放在/root/es1 中,經過如下命令建立一個 es 容器:

docker run --name=es1 -itd -p 9200:9200 -p 9300:9300 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -v /root/es1:/opt/es -w /opt/es jre:v1 ./bin/elasticsearch -Des.insecure.allow.root=true

參數含義以下:

  • -w containerPath 設置容器工做目錄爲 containerPath

  上面的命令以 es1 爲容器名,映射 9200,9300 到宿主機端口,以./bin/'elasticearch -Des.insecure.allow.root=true建立 es 容器。最後加的參數爲了讓 es 可以以 root 在容器中啓動。

建立 es 集羣

  將以前的 es1 複製一份命名爲 es2 做爲節點 2。要讓兩個 es 節點構成 es 集羣,須要讓節點間可以進行通訊,這裏使用--link參數來讓 es2 可以連上 es1 構成集羣。--link用法以下:

--link containerName[:alias]

es2 啓動命令以下:

docker run --name=es2 -itd -p 9201:9200 -p 9301:9300 --link es1 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -v /root/es2:/opt/es -w /opt/es jre:v1 ./bin/elasticsearch -Des.insecure.allow.root=true

而後就能在 es2 中經過 es1 的容器名訪問到 es1(實際是在 es2 的 host 中增長了一條記錄,將 es1 指向 es1 的 IP,該 IP 是 docker 的虛擬網卡分配的 IP)。

  可是使用--link 有一些侷限,經過該參數聯通的容器必須存在。所以該參數只能用在 B 依賴 A 的狀況,若是同時 A 也依賴 B(也就是 A,B 要可以相互訪問到),這種狀況下就不能經過 link 來實現了,緣由你們應該可以想到。。。

部署 activeMQ

  在容器中啓動 activeMQ 與啓動 es 稍有不一樣。activeMQ 默認是後臺啓動的,啓動完成後啓動程序就會退出,所以若是直接以./bin/activemq start(假設當前目錄在 activemq 中),啓動容器會發如今 activemq 啓動成功後容器就中止運行了。會出現這種狀況是由於容器中啓動的第一個進程結束後,容器就會被docker關閉掉。因此呢咱們只需讓第一個進程不結束就好了,所以須要咱們編寫一個啓動腳原本啓動 activemq 並監測運行狀況,一旦 activemq 進程掛掉,就結束啓動腳本,不然一直運行。啓動腳本代碼以下:

#!/bin/bash

#使用sh腳本啓動activemq,而後定時判斷服務是否被關閉,關閉後退出腳本,不然一致循環。
#爲避免docker容器在active自帶的啓動腳本運行結束後就關閉容器了。

#獲取啓動pid
out=`./bin/activemq start`
echo "$out"

pid=`echo $out | grep -Eo "pid '[0-9]+'" | grep -Eo "[0-9]+"`

echo "當前mq進程pid爲:${pid}"

if [ ${#pid} = 0 ]; then
  echo "啓動失敗"
  exit 0
fi

while true; do
  num=`ps -e | grep -cwE "$pid"`
  if [ $num = 0 ]; then
    echo "進程異常關閉"
    exit 0
  fi
  sleep 1
done

  而後以該腳本做爲啓動腳原本啓動容器便可。啓動命令以下:(假設 activemq 目錄爲/opt/activemq,啓動腳本路徑爲/opt/activemq/start.sh)

docker run --name=activemq -itd -p 8161:8161 -p 61616:61616 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -v /root/activemq:/opt/activemq -w /opt/activemq jre:v1 /bin/bash ./start.sh

部署 java 環境包

  仍是使用以前製做的 jar 鏡像來啓動 java 應用,這裏以部署 jar 包爲例,若是部署 war 包則須要在 tomcat 鏡像上部署。特別注意下容器的時間和時區設置,不然 java 程序中沒法獲取到正確的時間和時區。這裏經過映射宿主機的 localtime 和 timezone 文件來讓容器時間和時區與宿主機相同。啓動命令以下:

# 啓動oms
docker run -itd --name=oms -p 8082:9090 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -v /root/oms.jar:/opt/oms.jar  -w /opt --link es1 --link activemq --link oms-mysql --link eureka-server  jre:v1  java -jar oms.jar

# 啓動das
docker run -itd --name=das -p 8083:9099 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone -v /root/das.jar:/opt/oms  -w /opt --link es1 --link activemq --link oms-mysql --link eureka-server  jre:v1  java -jar das.jar

  本篇只是記錄瞭如何使用一容器一進程的方式來部署 java 應用.

PS:不推薦這麼直接手擼命令,建議使用 docker-compose

本篇原創發佈於 Flex 的我的博客:點擊跳轉

相關文章
相關標籤/搜索