docker——釋出一個應用程式
docker——釋出一個java應用程式
一、安裝docker
使用docker之前,需要在物理機上安裝docker。安裝過程可參考docker官網,安裝完成之後,執行docker。不同的作業系統,docker的安裝和啟動不同。
二、待發布的java程式說明
需要釋出的java服務目錄結構如下:
docker-test/
|-bin/
| |-server.sh
|-etc/
| |-config.edn
| |-logback.xml
|-target/
| |-docker-test.jar
| |-docker-test-standalone.jar
|-Dockerfile
Dockerfile
Dockerfile用來定義一個docker容器(container)的執行環境。
# 指定基礎映象openjdk8,用於執行java程式。
FROM openjdk:8
# 指定容器內的工作目錄
WORKDIR /app/
# 將Dockerfile所在目錄(docker-test)的bin目錄複製到容器內(/app/bin/)
COPY bin bin
# 將docker-test目錄下的etc目錄複製到容器內(/app/etc/)
COPY etc etc
# 將target下以standalone.jar結尾的jar包複製到容器內的lib目錄下(/app/lib/docker-test-standalone.jar).
COPY target/*standalone.jar lib/
# 將docker容器內的lib目錄下的jar包名字寫入到lib.txt(/app/lib.txt)
RUN ls lib/ > lib.txt
# 在docker容器內新建logs目錄(/app/logs/)
RUN mkdir logs
# 將物理機時間時區掛在到容器中,這樣容器時間與物理機系統時間一致
RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
server.sh
server.sh為java服務啟動指令碼,內容如下:
#!/bin/bash
## java服務啟動日誌記錄檔案在容器內的路徑
LOGFILE=/app/logs/start.log
## 進入容器內的bin目錄
cd /app/bin
## 從/app/lib.txt檔案中讀取要執行的jar檔案。
JAR=$(cat ../lib.txt)
## 執行程式
java ${JAVA_OPTS} -cp ../etc:../lib/${JAR} clojure.main -e "(use 'pay.system)(-main)" >> ${LOGFILE} 2>&1
注意這些目錄都是針對docker容器內的目錄。
config.edn
java程式執行時所需要的配置檔案:
{
;; 提供給網頁通訊的web服務
:outer-server {:host "0.0.0.0" :port 8035 :join? false}
;; 提供給內部服務,用於接收其他伺服器訊息的web服務地址
:inner-server {:host "0.0.0.0" :port 8042 :join? false}
}
0.0.0.0
表示該docker容器接收訪問埠8035和埠8042的所有ip。
logback.xml
logback日誌配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-10contextName %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日誌檔案 -->
<appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 攔截debug級別的日誌-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<file>/app/logs/docker-test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/app/logs/docker-test.log.%d{yyyy-MM-dd}</fileNamePattern>
<!-- 日誌檔案保留天數-->
<maxHistory>180</maxHistory>
</rollingPolicy>
<!-- 這裡使用普通的輸出格式-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 這裡是執行日誌 -->
<logger name="app" level="info" additivity="false">
<appender-ref ref="LOG_FILE" />
</logger>
<root level="info">
<appender-ref ref="LOG_FILE" />
</root>
</configuration>
注意,日誌檔案的路徑為docker容器內的路徑/app/logs/docker-test.log
而不是物理機上的檔案路徑。
三、打包程式的docker映象
進入到docker-test目錄,執行下面命令:
docker build -t docker-test:0.1.0
很多時候,我們會迭代釋出好多映象,就需要為這些映象打上tag(經常用版本號作為tag),此時要帶上-t
引數。如果不帶tag,則會預設使用latest作為TAG。
這樣打包後的映象被放在本地,可以使用下面命令檢視本地映象:
docker images -a
可以使用命令刪除一個本地映象:
docker rmi docker-test:0.1.0
四、執行docker容器
docker run -itd –name docker-test -e JAVA_OPTS=’-Xmx368m -Dfile.encoding=UTF-8 -Duser.timezone=GMT+08’ -p 8035:8035 -p 8042:8042 -v
/Users/admin/docker-test/logs:/app/logs -v /Users/admin/docker-test/etc:/app/etc
docker-test:0.1.0 /app/bin/server.sh
-d:
表示在後臺執行該docker容器
-i:
表示保留STDIN(標準輸入),用於控制檯互動 。
-t:
分配tty裝置,該可以支援終端登入 。
-p:
指定埠或ip對映,將物理機上的8035埠與docker容器的8035埠對映;將物理機上的8042埠與docker容器的8042埠對映。
-v:
給容器掛載儲存卷,掛載到容器的某個目錄。這裡講物理機上的/Users/admin/docker-test/logs
目錄掛載到docker容器的/app/logs目錄,這樣程式輸出的在logback.xml中指定的日誌,實際上被寫入到物理機/Users/admin/docker-test/logs
目錄下對應的日誌檔案中。
-e:
用於指定環境變數,比如例子中就設定了jvm執行時的引數(JAVA_OPTS),在啟動java程式時用到。注意-Duser.timezone=GMT+08
用於解決jvm時區與系統時區不一致,導致日誌檔案中輸出的時間為標準時區的時間,而不是本地時間。
目錄掛載的目的
- 掛載日誌目錄:因為程式執行的日誌檔案會非常之大,如果不將物理機的目錄掛在容器內,那麼日誌將儲存在容器內,而且是儲存在記憶體中,永不了多久,記憶體就會爆掉。
- 掛載配置檔案目錄:掛載配置檔案,使得可以在物理機上修改配置檔案,然後重新執行容器,達到改變配置的目的。
- 注意: 如果docker是部署在叢集(如k8s)中,那麼無法使用目錄掛載,因為你無法確定容器會執行在叢集中哪個物理機上。此時,你的配置最好通過環境變數傳遞,日誌則可以輸出到標準輸出。
docker-test:0.1.0 /app/bin/server.sh
:執行docker-test:0.1.0映象的/app/bin/server.sh指令碼。
至此,一個容器便啟動成功。可以嘗試訪問物理機地址的8035或8042埠,驗證是否程式是否正常執行。
但這樣執行的話,容器其實是阻塞在執行指令碼/app/bin/server.sh
的狀態(因為在指令碼中,並沒有指定程式在後臺執行),此時我們不能通過docker的attch
命令進入到容器。
可以通過如下命令執行docker容器:
docker run -itd –name docker-test -e JAVA_OPTS=’-Xmx368m -Dfile.encoding=UTF-8 -Duser.timezone=GMT+08’ -p 8035:8035 -p 8042:8042 -v
/Users/admin/docker-test/logs:/app/logs -v /Users/admin/docker-test/etc:/app/etc
docker-test:0.1.0 /bin/bash
這樣容器內會啟動/bin/bash終端,通過命令:
docker ps -a
可以找到容器ID(containerID),通過命令:
docker attach containerID
可以進入到該容器,此時介面和普通的unix命令列介面一樣。在容器內的命令列介面中,輸入命令:
./bin/server.sh
即可啟動java程式。
可以使用如下命令檢視映象的容器是否啟動成功(在STATUS中如果為up..則啟動成功,如果為exit…則未啟動成功):
docker ps -a
五、其他常用docker命令
停止容器
docker stop containerID
刪除容器
docker rm containerID
進入容器
首先通過docker ps -a
命令可以檢視到正在執行的容器ID(CONTAINER ID)。如果容器內的程序是以後臺執行的方式啟動的,則可以使用命令:
docker attach containerId
進入容器。
如果容器內的程序不是以後臺方式啟動的,那麼就無法通過attach命令進入,可使用命令:
docker exec -it containerID /bin/bash
進入。
匯出映象檔案
docker save -o [匯出後的檔名] [映象名稱]
如,將test-0.1.0:test
映象匯出為test-0.1.0.tar
:
docker save -o test-0.1.0.tar test-0.1.0:test
匯入映象檔案
docker load –input [匯出後的檔名]
如,將上面匯出的test-0.1.0.tar
再匯入:
docker load –input test-0.1.0.tar
檢視docker容器中標準輸出內容
docker logs [容器名稱或容器ID]
拉取docker映象
docker pull [映象地址]