Docker image 映像檔的匯入與匯出:容器化離線部署的關鍵步驟

Docker 是一個 Open source 的容器化平台,可以輕鬆地打包、部署和運行你的應用程式。
Docker image (映像檔) 是該平台重要元件,它是一個輕量級、可執行、可快速打包的軟體包,不只是應用程式所需的執行檔,還包含運作環境和環境設定。

因為一些特殊需求,需要離線安裝 (offline install) 或者是有些時候你可能沒有一個可以使用私有 docker registry,
你可能會需要這些指令,因有常常忘記故筆記一下。

docker image 匯出

首先,先列出有什麼 images

$ docker image ls

這指令會列出所有你曾經用過的 images

找到你要的 images

然後用 docker save 來匯出 image

$ docker save myimage:latest | gzip > myimage_latest.tar.gz

docker image 匯入

在別台機器,使用 docker load 來匯入 image

docker load --input myimage_latest.tar.gz

備註:官方文件有說 docker load 除了可以直接輸入

  • *.tar 打包檔案(未壓縮)
  • *.tar.gz 壓縮檔案( gzip 壓縮格式)
  • *.tar.bz2 壓縮檔案( bzip2 壓縮格式)
  • *.tar.xz 壓縮檔案( xz 壓縮格式)

當然還是建議放在類似 Docker hub 這樣的 registry 比較好,
如果 docker hub 私有 registry 方案不符合需求,
三大雲端也有提供對應的服務,
有地端 (on-premise) 伺服器自建 docker registry 的方式
不過這個就是另外一個故事了

另外, Kubernetes (k8s) 就非常不建議用匯出匯入這種方式來做,
因為它是叢集自動部署的,你不知道它每次會部署在哪一台機器(除非你有特別指定),
如果你要做類似這樣匯入匯出,你需要在每一個 Node 都做匯出匯入,曠日費時,
建議還是架一個 docker registry 比較理想。

參考資料

[教學] 用 Docker 來架設 LibreNMS 架設網路服務監控系統

LibreNMS 是一套 Open source 的功能完整的網路監控系統,
使用 SNMP (Simple Network Management Protocol) 協定來搜集電腦系統的資料。

初次研究後,就發現它可以協助解決設備很多在線上,
測量設備穩定性的事情。
就算該裝置沒有支援 SNMP,也可以使用純 ping 的方式來監控所有線上的設備。
就一步一步帶大家怎麼設定與架設。

LibreNMS 系列文:

以下使用 Docker 裝在 Linux 主機上。
至於 Linux 版本就看大家喜好,
以下示範使用 Ubuntu 系統,若是其他發佈版可以依樣畫葫蘆稍加修改。

我們今天用的是 jarischaefer/docker-librenms 套件來架設,
如果作者版本有更新安裝方式,再煩請告知。

GitHub 位置:
https://github.com/jarischaefer/docker-librenms

Step1. 產生密鑰

使用指令產生密鑰

$ sudo docker run --rm jarischaefer/docker-librenms generate_key

每台系統密鑰皆不相同,不可以直接複製。
如果有多台要架設,請記得更換密鑰!(這步驟很常忘記)

Step2. 編輯 docker-compose.yml

有關 docker 的設定方式就不贅述了。
有用過 docker 的朋友應該很熟悉 docker-compose 這指令。

現在要來做一個新的 docker-compose.yml

docker-compose.yml

version: '3.5'

services:
  web:
    image: jarischaefer/docker-librenms
    restart: always
    ports:
      - '80:80'
    volumes:
      - ./librenms_data/logs:/opt/librenms/logs
      - ./librenms_data/rrd:/opt/librenms/rrd
    environment:
      APP_KEY: base64:NA......................................SdA=
      DB_HOST: librenms_database
      DB_USER: librenms
      DB_PASS: Tuq.........tai
      DB_NAME: librenms
      POLLERS: 16
      BASE_URL: http://192.168.1.2
      TZ: Asia/Taipei
    depends_on:
      - mysql
  mysql:
    image: mariadb:10.5
    container_name: librenms_database
    restart: always
    volumes:
      - ./librenms_data/mysql:/var/lib/mysql
    environment:
      TZ: Asia/Taipei
      MYSQL_ROOT_PASSWORD: Cho.........lan
      MYSQL_USER: librenms
      MYSQL_PASSWORD: Tuq.........tai
      MYSQL_DATABASE: librenms

重要參數說明

web 部分

  • APP_KEY:密鑰(每台電腦皆不同,請自行產生)
  • DB_HOST:mysql 的 IP 位址(不需修改)
  • DB_USER:mysql 使用者
  • DB_PASS:mysql 密碼
  • DB_NAME:mysql 資料庫名稱
  • POLLERS:輪詢器數量
  • BASE_URL:預設網址(很重要,請記得改!就算是本機服務,也請修改成正確的網址。)
  • TZ:時區,這裡設定台灣 (Asia/Taipei)

mysql 資料庫部分

這裡使用 MariaDB 資料庫,要換成 mysql 5.7 也可以。

  • TZ:時區(與網頁伺服器一致即可)
  • MYSQL_ROOT_PASSWORD:資料庫 root 密碼
  • MYSQL_USER :使用者(與 DB_USER 一致即可)
  • MYSQL_PASSWORD :密碼(與 DB_PASS 一致即可)
  • MYSQL_DATABASE :資料庫名稱(與 DB_NAME 一致即可)

Step3. 建立資料夾

建立相關路徑的資料夾,讓它能夠掛載。

$ mkdir -p ./librenms_data && \
mkdir -p ./librenms_data/logs && \
mkdir -p ./librenms_data/rrd && \
mkdir -p ./librenms_data/mysql

Step4. 啟動整組服務

利用 docker-compose 把整組服務啟動。

$ sudo docker-compose up -d

Step5. 初始化資料庫

服務整組起來之後,網頁瀏覽器應該可以看到這個訊息:

Database inconsistencies found during a database error, please fix to continue.

Your database is out of date!

不用太緊張,這是正常現象,等下下指令來初始化資料庫。

首先要先找到 librenms_web 的 container,
如果是 docker-compose 整組起來的話,可能會叫做 librenms_web_1
執行指令前可以用 docker ps 指令來查看你的目前起的服務名稱(或 ID),確認一下。

$ sudo docker exec librenms_web_1 setup_database

這步驟是初始化它 LibreNMS 的資料庫。
如果失敗了,整個服務會起不來。

Step6. 建立 admin 管理者

它服務跑起來預設是 「沒有任何帳號的」,
我們用該指令來建立 admin 管理者

$ sudo docker exec librenms_web_1 create_admin

librenms_web_1 名稱為 container_id,
可用 docker ps 指令來查看你的目前起的服務名稱(或 ID)。

這指令將會建立一個 admin 管理者:

記得去改密碼。記得去改密碼。記得去改密碼。
很重要講三次。

瀏覽你的本機網址,就可以看到 LibreNMS 的主頁面了。

參考資料

Docker 設定避開衝突網段 ( 172.17.0.0/16 )

Docker 的好,用過的人就知道,
然而 Docker 在特定的網段裡面(例如: 172.17.x.x),會造成衝突。

嚴重造成 host 整台主機連不進來,無法連線。

這個時候要修改你的 Docker 預設網段,讓他跳過跟外界相符合的網段。

註:如果 你的開發機 (client) 與 你的伺服器 (server),兩個端點都有裝 Docker,
那兩個端點都要調整,跳開其網段。

註:預設 Docker 使用 172.17.0.0/16 網段。

修改 Docker 預設網段

Linux 系統的話,建立(或修改)daemon.json 這個檔案
(這個檔案預設是沒建立的,請自行建立。)

$ sudo vi /etc/docker/daemon.json

以下是範例格式,為 JSON 格式:

{
  "log-driver": "journald",
  "log-opts": {
    "tag": "{{.Name}}"
  },
  "default-address-pools": [
    {
      "base": "172.6.0.0/16",
      "size": 24
    }
  ],
  "bip": "172.7.0.1/16"
}

修改 bipdefault-address-pools 的欄位,輸入一個新的不衝突的網段即可。
(範例是改成 172.7.0.1/16172.6.0.0/16

  • bip 欄位是 docker 預設會開啟的網段。
  • default-address-pools 欄位是 docker-compose 如果有設定 network 區段的話,預設會配給的網段區域。

然後重新啟動 Docker 服務

$ sudo systemctl restart docker

這樣你的主機就會連線正常了。

自訂你自己服務的網段

在某些用途下你會需要一個特定幾個 container 能相互溝通的網路環境
你需要修改你的 docker network create 指令

例如:

$ sudo docker network create mynetwork --subnet=172.6.0.0/16

加上 --subnet= 參數,手動指定網段給他。

使用 docker-compose ?

如果是使用 docker-compose 的話,你可以這樣調整 networks 段落,

docker-compose.yml

version: '3.5'

services:
  web:
    image: crccheck/hello-world
    ports:
      - '80:8000'
    networks:
      - mynetwork
networks:
  mynetwork:
    ipam:
      config:
        - subnet: '172.6.0.0/16'

如果你要寫完整一點,這樣也是可以的。

networks:
  mynetwork:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: '172.6.0.0/16'
          gateway: '172.6.0.1'

ipamconfig 段落設定 subnetgateway 即可。

爾或者,修改 /etc/docker/daemon.json 中的 default-address-pools 的欄位,前面已經說過就不贅述了。

怎麼驗證?

你可以用 netstat 指令查詢

$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG        0 0          0 eth0
172.6.0.0       0.0.0.0         255.255.0.0     U         0 0          0 br-c3ff076483d3
172.7.0.0       0.0.0.0         255.255.0.0     U         0 0          0 docker0

docker network ls 指令

$ docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
da8e2609c93e   bridge        bridge    local
0eef0fedfb81   host          host      local
79cd2edd8448   none          null      local
c3ff076483d3   mynetwork     bridge    local

其中你可以看到範例 c3ff076483d3 對應 mynetwork 網段為 172.6.0.0

參考資料