Docker、Docker Compose、Harbor 的使用

Docker 引擎是一種用于構建和容器化應用程序的開源容器化技術。它是一個服務端-客戶端結構的應用,主要有以下部分組成:

  1. Docker 守護進程:持久化的進程,監(jiān)聽 Docker Engine API 的請求
  2. Docker Engine API:與 Docker 守護進程交互用的的 RESTful API
  3. Docker 客戶端:命令行接口,通過客戶端將命令發(fā)送給守護進程

Dockerfile 一個文本文檔,Docker 可以通過讀取 Dockerfile 中定義的指令來自動構建鏡像。

Docker Compose 是一個用于定義和運行多個容器的 Docker 工具。Compose 使用 YAML 文件來配置應用程序的服務。然后,通過單個命令,就可以從配置中創(chuàng)建并啟動所有服務。

下面演示所用 Demo 地址:https://github.com/14032/gchat

Dockerfile

Docker 提供了一種構建鏡像方式叫 Dockerfile,下面是用來構建 gchat 項目鏡像的 Dockerfile 文件:

FROM maven:3-jdk-8-alpine
MAINTAINER "人間春蕩蕩 <人間春蕩蕩@126.com>"

WORKDIR /opt/gchat
ADD gchat.war .
RUN jar -xvf gchat.war

ENV TZ=Asia/Shanghai
EXPOSE 8080

ENTRYPOINT java -cp /opt/gchat org.springframework.boot.loader.WarLauncher
  1. FROM 用來指定鏡像所依賴的基礎鏡像,這里項目需要的是 JDK 環(huán)境
  2. MAINTAINER:作者信息
  3. WORKDIR:指定后續(xù)命令執(zhí)行的目錄,即后續(xù)的命令都將 /opt/gchat 作為當前目錄
  4. ADD:復制文件,將當前目錄下 gchat.war 包復制到鏡像 /opt/gchat/ 目錄下
  5. RUN:在容器中要執(zhí)行的 shell 命令
  6. ENV:指定環(huán)境變量,這里指定了時區(qū)
  7. EXPOSE:聲明服務監(jiān)聽端口(僅僅是聲明,并不會主動做端口映射)
  8. ENTRYPOINT:指定鏡像的入口啟動進程

Dockerfile 編寫完了,下面看下如何使用 Dockerfile 文件來生成鏡像。

#  構建鏡像命令
docker build -t gchat:1.0-SNAPSHOT .

-t 作用是給鏡像打個標簽,起個名字。

末尾 . 代表 Dockerfile 文件在當前操作的目錄下,否則可以通過 -f /opt/Dockerfile 參數(shù)來指定文件位置。

docker build 會加載當前目錄下的 Dockerfile 文件,然后按照順序,執(zhí)行文件中定義的命令。

docker build 執(zhí)行完成后,通過 docker images 命令查看鏡像列表:

$ docker images
REPOSITORY    TAG             IMAGE ID        CREATED         SIZE
gchat         1.0-SNAPSHOT    d97ec5bc1022    4 months ago    241MB

通過 docker run 來創(chuàng)建運行 gchat 容器:

docker run -d --network=host --name gchat \
--env jdbc.type="mysql" \
--env jdbc.username="root" \
--env jdbc.password="root" \
--env jdbc.driver="com.mysql.cj.jdbc.Driver" \
--env jdbc.url="jdbc:mysql://192.168.0.10:3306/gchat?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai" gchat:1.0-SNAPSHOT192

參數(shù) --network 用來指定容器運行的網(wǎng)絡模式,默認為 bridge 方式。host 則表示主機網(wǎng)絡模式,共享宿主機的網(wǎng)絡棧;若采用默認的 bridge 方式,則需要開啟端口映射 -p 8080:8082 ,將容器內(nèi)的 8082 端口映射在宿主機的 8080 端口供外部訪問。

http://127.0.0.1:8080/gchat

運行過程中,可通過 docker logs -f gchat 來查看容器項目日志輸出。

通過 docker ps 查看運行中的容器列表:

$ docker ps
CONTAINER ID  IMAGE                COMMAND                 CREATED     STATUS        PORTS   NAMES
12483291aa72  gchat:1.0-SNAPSHOT   "/bin/sh -c 'java -c…"  2 minutes   Up a minute           gchat

查看詳細信息使用 docker inspect 命令:

# 查看 gchat 容器信息
docker inspect gchat

# 查看 gchat 鏡像的信息:
docker image inspect gchat:1.0-SNAPSHOT

還有一種生成鏡像的方式是:docker commit 。

這個命令可以把一個正在運行的容器,直接提交為一個鏡像。

例如在內(nèi)網(wǎng)環(huán)境安裝 Jenkins ,不能訪問互聯(lián)網(wǎng),這個時候就可以先在本地運行 Jenkins 容器:

docker run -d --name jenkins -p 8084:8080 jenkins/jenkins:lts

運行成功后,訪問 http://127.0.0.1:8084/jenkins ,把需要的一些插件全部安裝后,對正在運行的容器執(zhí)行 docker commit 操作,這樣在容器之上的所有操作都會保存到新的鏡像里。

# 將運行中的容器 56b5168a7ae2 提交為鏡像 
docker commit 56b5168a7ae2 jenkins:self-v3

之后,可通過 docker save 命令導出鏡像,再通過 docker load 命令將鏡像加載至內(nèi)網(wǎng)中。

# 導出
docker save -o jenkins-lts-v3.tar jenkins:self-v3
# 導入
docker load -i jenkins-lts-v3.tar jenkins:self-v3

當然還可以通過 Volume 數(shù)據(jù)卷的功能,將宿主機目錄掛載到 Jenkins 所在容器內(nèi)的安裝目錄上,這樣所有的有關 Jenkins 文件增刪改都發(fā)生在宿主機上。

# 將 /opt/jenkins 掛載至容器內(nèi) jenkins 的安裝目錄
-v /opt/jenkins:/home/jenkins

如果想在運行中的容器中執(zhí)行 shell 命令,使用 docker exec 命令:

docker exec -it gchat /bin/sh

命令執(zhí)行后會進入容器的默認工作目錄,如果在 Dockerfile 中指定了工作目錄 WORKDIR,則會進入 Dokcerfile 指定的目錄,例如執(zhí)行 ls 默認顯示的就是 /opt/gchat 下的文件。

$ docker exec -it gchat ls
META-INF   WEB-INF    gchat.war  org

查看設置的環(huán)境變量 env:

$ docker exec -it gchat env

# Dockerfile 鏡像中指定
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
HOSTNAME=f3b50c9fcb00
LANG=C.UTF-8
JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk
JAVA_VERSION=8u212
JAVA_ALPINE_VERSION=8.212.04-r0
MAVEN_HOME=/usr/share/maven
MAVEN_CONFIG=/root/.m2
JAVA_OPTS=-Xms1024m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
HOME=/root

# 創(chuàng)建容器時指定
jdbc.type=mysql
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://mysql:3306/gchat?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
TZ=Asia/Shanghai

執(zhí)行 uname -a,查看 Linux 內(nèi)核版本:

# 容器內(nèi)執(zhí)行
$ docker exec -it gchat /bin/sh
/opt/gchat # uname -a
Linux king-ubuntu 4.15.0-108-generic #109-Ubuntu SMP Fri Jun 19 11:33:10 UTC 2020 x86_64 Linux
/opt/gchat # exit
# 宿主機
$ uname -a
Linux king-ubuntu 4.15.0-108-generic #109-Ubuntu SMP Fri Jun 19 11:33:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

首先要明確的是,容器與宿主機共享操作系統(tǒng)內(nèi)核,也就是說容器和鏡像是沒有內(nèi)核的,只有文件系統(tǒng)。我們有些服務器是華為 TaiShan,基于鯤鵬處理器 ARM 架構的 Linux 系統(tǒng),在剛開始使用 Docker 的時候,嘗試在其中啟動基于 X86 架構構建的鏡像,很顯然失敗了。

下面是官方文檔中 Docker 的特性說明,其中約束和隔離涉及到 Linux 的 Namespace 和 Cgroups 特性,大家可自行 Google 了解。

靈活:即使是最復雜的應用程序也可以被容器化。
輕量級:容器利用并共享主機內(nèi)核,使它們在系統(tǒng)資源方面比虛擬機效率更高。
可移植:您可以在本地構建、部署到云中,并在任何地方運行。
松散耦合:容器是高度自給自足和封裝的,允許您替換或升級一個容器,而不會破壞其他容器。
可擴展:您可以增加和自動分發(fā)跨數(shù)據(jù)中心的容器副本。
安全:容器對進程進行約束和隔離,而不需要用戶進行任何配置。

容器只是操作系統(tǒng)中的一個進程:

從根本上說,容器只不過是一個正在運行的進程,為了保持它與主機和其他容器的隔離,對它應用了一些附加的封裝特性。容器隔離最重要的是每個容器與自己的私有文件系統(tǒng)交互;這個文件系統(tǒng)由 Docker 鏡像提供。鏡像包括運行應用程序所需的一切代碼或二進制、運行時、依賴項和任何其他所需的文件系統(tǒng)對象。

# 查看進程號
$ docker top gchat
UID     PID      PPID    C    STIME    TTY    TIME           CMD
root    4038     4014    6    13:57     ?     00:00:14       java -cp ...

Harbor

Harbor 是構建企業(yè)級私有 Docker 鏡像倉庫的開源解決方案,就像 Nexus 是 Maven 的 JAR 倉庫管理器一樣。

Harbor 使用 Docker 方式來安裝啟動,并且通過 Docker Compose 工具來管理,所以請先確保 Docker 環(huán)境和 Docker Compose 工具已經(jīng)成功安裝。

Harbor 離線安裝包 harbor-offline-installer-v1.9.4.tgz 下載地址:

https://github.com/goharbor/harbor/releases

將安裝包解壓,Harbor 的配置文件 harbor.yml ,包括域名、端口號、初始密碼等配置:

# Configuration file of Harbor
hostname: 192.168.0.110
# http related config
http:
  port: 8089
harbor_admin_password: Harbor12345
......

在解壓后的文件夾下執(zhí)行 ./install.sh 命令進行安裝,輸出如下:

[Step 0]: checking installation environment ...
Note: docker version: 19.03.5
Note: docker-compose version: 1.25.3

[Step 1]: loading Harbor images ...
Loaded image: goharbor/harbor-core:v1.9.4
Loaded image: goharbor/clair-photon:v2.1.0-v1.9.4
... 略
[Step 2]: preparing environment ...
prepare base dir is set to /usr/local/harbor
Clearing the configuration file: /config/db/env
... 略
[Step 3]: starting Harbor ...
Creating harbor-log ... done
Creating registry      ... done
... 略
? ----Harbor has been installed and started successfully.----

安裝成功后,文件夾下會出現(xiàn)一個 docker-compose.yml 文件,YML 文件中定義了 Harbor 工具所需要創(chuàng)建的容器以及其它配置??梢酝ㄟ^ Docker Compose 命令來啟動、停止、卸載 Harbor 服務,關于 Docker Compose 的使用下面會介紹。

  • 創(chuàng)建 Harbor 服務所需容器并且啟動

    docker-compose -f /usr/local/harbor/docker-compose.yml -p harbor up -d

  • 停止并刪除 Harbor 服務所需容器

    docker-compose -f /usr/local/harbor/docker-compose.yml down

  • 啟動、停止、重啟 Harbor 服務

    docker-compose -f /usr/local/harbor/docker-compose.yml start/stop/restart

安裝成功后,執(zhí)行下 docker images 命令,查看此時的鏡像列表,輸出如下,這些鏡像皆是在執(zhí)行 ./install.sh 命令時構建的,即上面輸出中的 [Step 1]: loading Harbor images

goharbor/chartmuseum-photon    v0.9.0-v1.9.4    7fd23c6f1f36    127MB
goharbor/harbor-migrator       v1.9.4           899a03b70174    363MB
goharbor/redis-photon          v1.9.4           48c941077683    113MB
goharbor/clair-photon          v2.1.0-v1.9.4    ea69a6daa928    170MB
goharbor/notary-server-photon  v0.6.1-v1.9.4    3a02116cf089    143MB
goharbor/notary-signer-photon  v0.6.1-v1.9.4    289af497dbf0    140MB
goharbor/harbor-registryctl    v1.9.4           7259026fb1bb    103MB
goharbor/nginx-photon          v1.9.4           364c17f09df9    44MB
goharbor/harbor-log            v1.9.4           e0188c234aa2    82.3MB
goharbor/harbor-jobservice     v1.9.4           207acbcff6f5    141MB
goharbor/harbor-core           v1.9.4           a805deab5833    156MB
goharbor/harbor-portal         v1.9.4           cfd272546394    51.4MB
goharbor/harbor-db             v1.9.4           265c8c83954e    150MB
goharbor/prepare               v1.9.4           b2cded69458d    151MB

再執(zhí)行一下 docker ps 命令,查看此時有哪些運行中的容器,輸出如下,這些就是 Harbor 服務所需要的容器,它們的創(chuàng)建和啟動是在 ./install.sh 執(zhí)行的第三步完成的 [Step 3]: starting Harbor ...

CONTAINER ID   IMAGE                               NAMES
751a81c67e99   goharbor/nginx-photon:v1.9.4        nginx
7cb50d0224d4   goharbor/harbor-jobservice:v1.9.4   harbor-jobservice
c2751b9f1d81   goharbor/harbor-core:v1.9.4         harbor-core
2344cd81a05a   goharbor/redis-photon:v1.9.4        redis
89a8695d234a   goharbor/harbor-registryctl:v1.9.4  registryctl
f9c564f44ef2   goharbor/harbor-portal:v1.9.4       harbor-portal
c4661ab61769   goharbor/harbor-db:v1.9.4           harbor-db
86984dbff640   goharbor/registry-photon:v1.9.4     registry
3c36fe8023ef   goharbor/harbor-log:v1.9.4          harbor-log

瀏覽器訪問 Harbor 控制臺,賬號:admin 默認密碼:Harbor12345

Harbor Admin

Docker Maven Plugin

上面通過手動執(zhí)行 docker build 命令已經(jīng)成功構建了鏡像,這里再看下如何在項目通過 Maven 插件來自動構建鏡像并且發(fā)布至倉庫 Harbor 中。

筆者是在 Windows 的 IDEA 中構建,Docker 是通過虛擬機安裝的,所以首先需要配置 Docker 允許遠程連接。

編輯 vim /lib/systemd/system/docker.service ,將 ExecStart 追加參數(shù) -H tcp://0.0.0.0:2375

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

保存后,重啟:

systemctl daemon-reload
systemctl restart docker

通過瀏覽器訪問 http://192.168.0.110:2375/info 成功即可。

在 IDEA 中添加 Docker 配置:

在 IDEA 中查看 Docker 容器、鏡像信息:

docker maven 插件配置:具體參看 Spring Boot Demo 項目

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.2.2</version>
    <configuration>
        <serverId>docker-harbor</serverId>
        <dockerHost>http://192.168.0.110:2375</dockerHost>
        <registryUrl>192.168.0.110:8089</registryUrl>
        <imageName>192.168.0.110:8089/base/${project.build.finalName}:${project.version}</imageName>
        <dockerDirectory>${project.basedir}/bin/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.war</include>
            </resource>
        </resources>
        <imageTags>
            <imageTag>${project.version}</imageTag>
        </imageTags>
        <forceTags>true</forceTags>
        <pushImage>true</pushImage>
    </configuration>
</plugin>
  1. dockerHost 標簽可以指定 Docker 服務遠程地址
  2. registryUrl 指定倉庫地址,這里用的是自己搭建的 Harbor 鏡像倉庫
  3. imageName 指定鏡像名稱
  4. dockerDirectory 用來指定 Dockerfile 文件的位置
  5. imageTags 即指定鏡像版本號
  6. pushImage 表示是否將鏡像推送到指定的倉庫中,為 false 時,構建成功后不推送倉庫

構建前首先在 Maven 配置中添加 Harbor 用戶名密碼和 plugin 配置:

<server>  
  <id>docker-harbor</id>  
  <username>admin</username>
  <password>Harbor12345</password>
</server> 
<pluginGroups>
    <pluginGroup>com.spotify</pluginGroup>
</pluginGroups>

下面執(zhí)行命令進行構建并上傳至 Harbot:

mvn clean package docker:build -Dmaven.test.skip=true -Pdocker

輸出如下:

[INFO] Building image 192.168.0.110:8089/base/gchat:1.0
Step 1/9 : FROM maven:3-jdk-8-alpine
 ---> 7445f83cd169
Step 2/9 : MAINTAINER "人間春蕩蕩 <人間春蕩蕩@126.com>"
 ---> 6ec6024e4273
Step 3/9 : WORKDIR /opt/gchat
 ---> f48609ccaa2d
Step 4/9 : ADD gchat.war .
 ---> 7335b0f3485c
Step 5/9 : RUN jar -xvf gchat.war
... 略
Successfully built 6ce252273598
Successfully tagged 192.168.0.110:8089/base/gchat:1.0

構建成功后,登錄 Harbor,http://192.168.0.110/harbor 查看鏡像信息。

局域網(wǎng)內(nèi)可通過 docker pull 拉取 Harbor 上的鏡像:

docker pull 192.168.0.110:8089/base/gchat:1.0

docker push 默認推送地址是 Docker 官方倉庫 https://hub.docker.com/ ,你需要先注冊一個 Docker Hub 賬號,然后用 docker login 命令登錄后即可執(zhí)行 docker push 推送鏡像。 如要將本地鏡像推送至私人搭建的倉庫 Harbor,登錄時要指定鏡像倉庫地址:

docker login 192.168.0.110:8089

Docker Compose

編排工具就是來管理 Docker 容器的定義、配置和創(chuàng)建,筆者在 docker-compose.yml 文件中定義了三個服務,mysql、nginx、gchat,并且指定了它們之間的關聯(lián)關系。

version: '3.7'
services:
  mysql:
    image: mysql:latest
    container_name: mysql
    restart: always
    ports:
      - "3407:3306"
    volumes:
      - ./mysql/data/:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
      - ./mysql/sec:/var/lib/mysql-files
    environment:
      MYSQL_ROOT_PASSWORD: "root"
  gchat:
    image: com.demo/gchat:1.0-SNAPSHOT
    container_name: gchat
    restart: always
    ports:
      - "8087:8082"
    depends_on:
      - mysql
    environment:
      jdbc.type: "mysql"
      jdbc.username: "root"
      jdbc.password: "root"
      jdbc.driver: "com.mysql.cj.jdbc.Driver"
      jdbc.url: "jdbc:mysql://mysql:3306/gchat?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"
  nginx:
    image: nginx:1.17.8
    container_name: nginx
    restart: always
    depends_on:
      - gchat
    volumes:
      - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/html:/usr/share/nginx/html
      - ./nginx/logs:/var/log/nginx
    ports:
      - 80:80
    environment:
      - TZ=Asia/Shanghai

這里 mysql 容器的配置文件和數(shù)據(jù)被掛載到宿主機上,nginx 的配置文件也被掛載到了宿主機上,這樣即使刪除容器的話,數(shù)據(jù)也不會丟失;修改配置文件可直接在宿主機上進行編輯,無需通過 docker exec 命令進入容器內(nèi)修改(或者是通過 docker cp 來 copy 文件至宿主機內(nèi))。

執(zhí)行 docker-compose -p gchat up -d 命令來創(chuàng)建和啟動容器,此命令默認會在當前目錄下查找 docker-compose.yml 文件,也可手動指定文件位置 -f /opt/gchat/docker-compose.yml ,先看下輸出信息:

$ docker-compose -p gchat up -d
Creating network "gchat_default" with the default driver
Creating mysql ... done
Creating gchat ... done
Creating nginx ... done

默認的網(wǎng)絡模式為 network_mode: bridge 。

首先會創(chuàng)建一個名稱為 gc_default 的網(wǎng)絡,然后根據(jù)配置 依次創(chuàng)建容器 mysql、 gchat、nginx,并且以其容器名稱加入 gc_default 網(wǎng)絡中。這樣 Docker Compose 管理下的容器之間的相互訪問即可通過容器名稱加容器端口的方式。

也可以通過 docker network create 命令先創(chuàng)建網(wǎng)絡,然后在 yml 中進行配置。

docker network create -d bridge self-network
networks:
  default:
    external:
      name: self-network

通過 docker network ls 查看當前的網(wǎng)絡:

/opt/gchat$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
10b2aaa3c026        bridge              bridge              local
c5555d99ae9d        gchat_default       bridge              local
b6a883741497        host                host                local
0f969b2af1da        none                null                local

再查看下剛剛創(chuàng)建的網(wǎng)絡 gchat_default 的具體信息:docker network inspect gchat_default

$ docker network inspect gchat_default
......
"Name": "gchat_default",
"Driver": "bridge",
"IPAM": {
    "Driver": "default",
    "Config": [
        {
            "Subnet": "172.27.0.0/16",
            "Gateway": "172.27.0.1"
        }
    ]
},
"Containers": {
    "4e2eacd13160d9d5a98da97e61e5686418d6dd4f8592fef5f64c0ee622307d82": {
        "Name": "gchat",
        "MacAddress": "02:42:ac:1b:00:03",
        "IPv4Address": "172.27.0.3/16"
    },
    "6ff30a833674c4bf2629329d7a63e8b2070c8ea738b3e38c48ae5535addc4d43": {
        "Name": "nginx",
        "MacAddress": "02:42:ac:1b:00:04",
        "IPv4Address": "172.27.0.4/16"
    },
    "d530fef73b38301a9b94421ec213c274129b01f494138786ab4175a8d65f4037": {
        "Name": "mysql",
        "MacAddress": "02:42:ac:1b:00:02",
        "IPv4Address": "172.27.0.2/16"
    }
},
......

信息很清晰,默認的網(wǎng)絡驅(qū)動是:bridge,網(wǎng)絡名稱為:gchat_default,網(wǎng)段為 172.27.0.0/16,給每一個容器都分配了一個 IP。

在用戶自己定義的 Docker 網(wǎng)絡中,容器名稱的 DNS 解析會自動發(fā)生,Docker 內(nèi)嵌的 DNS 服務維護容器名稱及其 IP 地址,如容器正在使用定義的 Docker 網(wǎng)絡,無需執(zhí)行任何操作,它們可以使用主機名自動找到對方。如下:ping 其它的容器名稱

$ docker exec -it gchat ping mysql
PING mysql (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.050 ms
64 bytes from 172.27.0.2: seq=1 ttl=64 time=0.102 ms

$ docker exec -it gchat ping nginx
PING nginx (172.27.0.4): 56 data bytes
64 bytes from 172.27.0.4: seq=0 ttl=64 time=0.045 ms
64 bytes from 172.27.0.4: seq=1 ttl=64 time=0.060 ms

在 Docker 中,容器的主機名默認為容器的 ID,也可以通過 --hostname 參數(shù)來指定,通過 docker exec 查看容器的 hosts 文件:

$ docker exec -it mysql cat /etc/hosts
172.27.0.2  d530fef73b38

查看正在運行的容器:

$ docker ps
CONTAINER ID   IMAGE        COMMAND                  STATUS          PORTS                      NAMES
6ff30a833674   nginx:1.17.8  "nginx -g "             Up 19 minutes   80->80/tcp   nginx
4e2eacd13160   gchat:1.0     "/bin/sh -c 'java -c…"  Up 19 minutes   8080/tcp, 8087->8082/tcp   gchat
d530fef73b38   mysql:latest  "docker-entrypoint.s…"  Up 19 minutes   33060/tcp, 3407->3306/tcp  mysql

對于容器內(nèi)的 DNS 配置,如果宿主機的 /etc/resolv.conf 內(nèi)容發(fā)生改變,Docker 進程會監(jiān)聽到這些改變,并將變化同步至容器的 /etc/resolv.conf 。但前提是,只有在容器停止時,才會同步這些配置的更改。因此,要想使宿主機上配置的 DNS 生效,就需要停止容器后重新啟動。

執(zhí)行 docker inspect gchat 查看容器如下信息:

# system
"ResolvConfPath": "/var/lib/docker/containers/de88cfcfcb410dba67b4bcb7da/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/de88cfcfcb410dba67b4bcb7da/hostname",
"HostsPath": "/var/lib/docker/containers/de88cfcfcb410dba67b4bcb7da/hosts",

網(wǎng)絡信息:

"Networks": {
    "gchat_default": {
        "Aliases": [
            "gchat",
            "de88cfcfcb41"
        ],
        "NetworkID": "7a140855e53ec5d86af3733dc7b0ef10ed95437811623eb1d00f6185b7cfcaf8",
        "Gateway": "172.30.0.1",
        "IPAddress": "172.30.0.3",
        "MacAddress": "02:42:ac:1e:00:03",
    }
}

數(shù)據(jù)卷信息:

# Volumn
"Mounts": [
    {
        "Type": "bind",
        "Source": "/opt/gchat/mysql/data",
        "Destination": "/var/lib/mysql",
        "Mode": "rw", "RW": true,
        "Propagation": "rprivate"
    },
    {
        "Type": "bind",
        "Source": "/opt/gchat/mysql/my.cnf",
        "Destination": "/etc/mysql/my.cnf",
        "Mode": "rw", "RW": true,
        "Propagation": "rprivate"
    }
]

查看日志的話,可通過 docker logs -f gchat,也可通過 docker-compose logs -f gchat 來查看。

如果想要強制重建某個容器,可使用 --force-recreate 參數(shù):

docker-compose up -d --force-recreate mysql

否則只會在容器配置有更改時才會重建容器,容器之間根據(jù) depends_on 參數(shù)設置了依賴關系,代表了其創(chuàng)建啟動的順序。重建某個容器時,會先重建其依賴的容器,例如重建 gchat 容器時:

$ docker-compose up -d --force-recreate gchat
Recreating mysql ... done
Recreating gchat ... done

停止并刪除所有容器命令:

docker-compose down

刪除某個容器,默認只能刪除已停止的容器,-f 強制刪除:

docker rm -f nginx

磁盤空間使用分析:docker system df

空間清理 docker system prune,此命令會刪除:

  1. 所有已停止的容器
  2. 所有不被任何容器使用的 network
  3. 所有懸空鏡像,即未被任何容器引用的鏡像

這里要注意區(qū)分主機端口和容器端口,例如對于上面定義的 mysql 容器,3407 是主機端口,3306 是容器端口,網(wǎng)絡化的容器服務之間的通信使用容器端口,例如 gchat 連接 mysql 數(shù)據(jù)庫使用的是 mysql:3306;而對于外部網(wǎng)絡訪問則需要使用主機端口,例如在其他電腦中通過 Navicat 連接 mysql 則需要使用 3407 端口。

此外,docker 也提供了一些查看容器資源統(tǒng)計信息的命令。

通過 docker stats 查看容器 cpu、mem 使用情況, MEM USAGE / LIMIT 容器使用的總內(nèi)存和允許使用的總內(nèi)存,未做限制時,允許使用的量為宿主機總內(nèi)存。

$ docker stats
CONTAINER ID  NAME    CPU %    MEM USAGE / LIMIT     MEM %   NET I/O          BLOCK I/O        PIDS
93a546af2006  nginx   0.00%    108.5MiB / 4.837GiB   2.19%   4.18kB / 0B      4.76MB / 0B      5
f3b50c9fcb00  gchat   1.80%    437.3MiB / 4.837GiB   8.83%   27kB / 21.7kB    60.3MB / 0B      32
64090ff0d7b0  mysql   0.46%    395MiB / 4.837GiB     7.98%   28.8kB / 20.3kB  72.1MB / 18.8MB  40

查看容器在宿主機中的進程號 docker top [containerId or Name]:

$ docker top f3b50c9fcb00
UID      PID    PPID   C   STIME   TTY    TIME       CMD
root     4001   3975   6   15:21    ?     00:00:12   java -cp /opt/gchat -Xms1024m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m org.springframework.boot.loader.WarLauncher

下面對 gchat 容器的 cpu、memory 資源進行限制,不同版本寫法略有差別,具體參看官方說明:

https://docs.docker.com/compose/compose-file/#resources

deploy:
  resources:
    limits:
      cpus: "0.20"
      memory: 2G  

添加如上資源限制標簽后,這時通過 docker-compose up -d --force-recreate gchat 重建容器時,會有如下提示,設置的資源限制 deploy 屬性被忽略,未起作用。

WARNING: Some services (gchat ) use the ‘deploy’ key, which will be ignored. 
Compose does not support ‘deploy’ configuration - use docker stack deploy to deploy to a swarm.

原因是由于做了資源限制, 并且沒有使用 swarm,所以要加上 --compatibility 參數(shù),它會將 version: 3.x 版本設置資源限制的方法轉(zhuǎn)換回 version: 2.x 兼容的屬性。

docker-compose --compatibility up -d --force-recreate gchat

# 參數(shù)含義
--compatibility If set, Compose will attempt to convert keys in v3 files to their non-Swarm equivalent

可以通過運行 docker-compose --compatibility config 來驗證配置,會看到資源限制屬性被翻譯成 cpus 和 mem_limit。

$ docker-compose --compatibility config
......
services:
  gchat:
    container_name: gchat
    cpus: 0.2
    mem_limit: 2G
    depends_on:
      mysql:
        condition: service_started
  ......
version: '2.3'

Docker Compose 配置中除了指定鏡像名稱外,還可以指定 Dockerfile 文件,啟動時會先根據(jù) yml 中 Dockerfile 的配置來創(chuàng)建鏡像,詳情參看:

https://docs.docker.com/compose/compose-file/#build

~ END ~

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容