1. 程式人生 > >docker——釋出一個應用程式

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 [映象地址]