Docker 入門:告別部署噩夢!

Docker 入門:告別部署噩夢!

入門級開發者常面臨程式碼更新、發佈與部署效率低下的痛點,以及維護環境一致性的挑戰。在開發環境中運作順暢的程式碼,到另一台機器上可能出現錯誤。在雲端運算時代,使用傳統方法部署程式碼已顯得過時。本文將為你介紹 Docker。

Docker 基於 Go 語言開發,並遵循 Apache 2.0 授權開源,是一款應用程式容器引擎。這項容器化技術讓開發者能將應用程式及其依賴封裝成輕量、可移植的容器。這些容器可部署在任何主流 Linux 機器上,無需擔心環境差異。

Docker 與虛擬機器(VMs)的比較

如前述,Docker 使用了虛擬化技術。談到虛擬化,就不得不提虛擬機器(VM)。由於兩者都依賴虛擬化,自然會好奇它們的差異。讓我們深入探討。

首先,來看典型的 VM 架構圖。在基礎設施(代表底層硬體)之上,有 hypervisor(虛擬機監視器)。它作為實體伺服器與作業系統之間的中介,允許多個作業系統與應用程式共享底層硬體。虛擬機器在主機作業系統之上運行多個不同的作業系統,並透過 hypervisor 存取底層硬體。

如果你需要執行三個隔離的應用程式,就會建立三個虛擬機器。這意味著 hypervisor 上將運行三個作業系統,導致大量的資源開銷。

典型的 VM 架構圖

(注意:圖中 Hypervisor 上方應有 Host Operating System)

相比之下,Docker 非常輕量。它的守護行程(Docker Daemon)取代了 hypervisor,直接運行在作業系統上。應用程式的原始碼與依賴項被封裝成 Docker 映像檔(Image)。Docker 引擎再用此映像檔建立容器(Container)。不同的應用程式在隔離的容器中運行。

此外,Docker 守護行程直接與作業系統通訊,為 Docker 容器分配資源。由於沒有完整作業系統的開銷,容器啟動時間從虛擬機器的數分鐘縮短至 Docker 容器的毫秒等級,大幅提升效率,並節省大量磁碟空間與其他系統資源。

雖然 Docker 有顯著優勢,但它並非完全取代虛擬機器。每種技術各有擅長。虛擬機器擅長隔離整個執行環境,雲端服務供應商常用 VM 來隔離不同用戶。而 Docker 通常用於隔離不同的應用程式。

如何使用 Docker

Docker 安裝(以 CentOS 7 為例)

  1. 安裝必要的系統工具:
yum install -y yum-utils device-mapper-persistent-data lvm2 
  1. 更新系統核心與 yum 快取:
yum update
yum makecache fast
  1. 安裝 Docker 並啟動:
yum -y install docker-ce
systemctl start docker 
  1. 測試 Docker 是否安裝成功:
docker run hello-world 

若畫面上出現 “Hello from Docker”,恭喜你!安裝完成。

概念

在深入 Docker 之前,先了解幾個關鍵概念,讓學習過程更順利。

  1. Docker 映像檔(Image):Docker 映像檔是用來建立 Docker 容器的範本。
  2. Docker 容器(Container):Docker 透過映像檔建立容器,用於執行一組獨立的應用程式。
  3. Docker 倉儲(Registry):儲存映像檔的程式碼倉庫。

通常,我們從 Docker 倉儲下載合適的映像檔,再用它建立容器來執行應用程式。

範例

透過兩個常見範例來串聯這些概念,說明如何使用 Docker。

用 Docker 安裝 Python

如前所述,使用 Docker 容器的第一步是從倉儲下載對應的映像檔。這就引出了本教學的第一個指令:

  • 用途: 在映像檔倉儲中搜尋特定的映像檔。
  • 語法: docker search [OPTIONS] TERM
  • 範例: docker search python
  • 說明: 在倉儲中搜尋與 Python 相關的映像檔。
[root@novita ~]# docker search pythonINDEX       NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/python                           Python is an interpreted, interactive, obj...   4356      [OK]
docker.io   docker.io/django                           Django is a free web application framework...   856       [OK]
docker.io   docker.io/pypy                             PyPy is a fast, compliant alternative impl...   196       [OK]
docker.io   docker.io/kaggle/python                    Docker image for Python scripts run on Kaggle   125                  [OK]
docker.io   docker.io/arm32v7/python                   Python is an interpreted, interactive, obj...   38
docker.io   docker.io/centos/python-35-centos7         Platform for building and running Python 3...   36

我們選擇標籤(版本)為 3.7 的官方映像檔。

docker pull

  • 用途: 從映像檔倉儲拉取或更新指定的映像檔。
  • 語法: docker pull [OPTIONS] NAME:TAG
  • 範例: docker pull python:3.7
  • 說明: 從倉儲下載標籤為 3.7 的 Python 映像檔。
[root@novita ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============>                                     ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================>      ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==>                                                ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7

現在 Docker 已下載指定的映像檔。若要查看現有的 Docker 映像檔:

docker images

  • 用途: 列出本機的映像檔。
  • 語法: docker images [OPTIONS] [REPOSITORY[:TAG]]
  • 範例: docker images
  • 說明: 查看所有本機的 Docker 映像檔。
[root@novita ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker.io/python        3.7                 42d620af35be        6 days ago          918 MB
docker.io/rabbitmq      3-management        7aae48fa6ef6        7 days ago          179 MB
docker.io/golang        latest              f50db16df5da        9 days ago          774 MB

python3.7 映像檔已存在。接下來用此映像檔建立容器。

docker run

建立容器前,先簡單介紹 ID。在 Docker 中,ID 用於唯一識別映像檔或容器。我們透過「指令 + ID」來操作。例如,上方 python3.7 的 Image ID 是 42d620af35be。

  • 用途: 建立一個新容器。
  • 語法: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

為了測試 Python 環境,先在本機建立一個 hello.py 檔案:

#!/usr/bin/python 
import sys 

print("Hello, Docker!") 
print(sys.version)  # 輸出 Python 版本號 

假設此程式碼儲存在 /root/code/python:

[root@novita python]# docker run  -v $PWD:/usr/src/code  -w /usr/src/code python:3.7 python hello.py 
Hello, Docker! 
3.7.4 (default, Jul 13 2019, 14:04:11) [GCC 8.3.0] 

讓我們拆解這個指令:

  • docker run:建立容器。
  • -v $PWD:/usr/src/code:將本機目錄掛載到 Docker 容器內。此處將執行指令的目錄掛載到容器內的 /usr/src/code。冒號分隔本機路徑與容器路徑。你也可以使用絕對路徑取代 $PWD
  • -w /usr/src/code:設定容器的工作目錄。由於 Python 程式碼目錄已掛載到 /usr/src/code,因此將它設為工作目錄。
  • python:3.7:指定映像檔。你也可以使用 Image ID 取代。
  • python hello.py:在容器內執行此指令。

想想看: 如果你有一個 hello.go 檔案在 /root/data/,想要使用 Image ID 為 f50db16df5da 的 Golang 容器來執行它,指令應該是什麼?(提示:執行 Go 程式碼的指令是 go run FILENAME

用 Docker 安裝 MariaDB

假設你現在能夠搜尋並下載 MariaDB 的映像檔,接下來重點在於啟動它。資料庫之類的服務需要對應的連接埠在主機上開啟。如何用 Docker 實現呢?我們使用連接埠對應,類似於掛載目錄的方式。

[root@novita python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456  --restart unless-stopped 3a2ef06682ac 
  • -d:讓容器在背景執行。
  • -p 3306:3306:將容器內的 3306 連接埠對應到主機的 3306 連接埠。
  • -e MYSQL_ROOT_PASSWORD=123456:設定 MariaDB 的 root 密碼為 123456。
  • --restart unless-stopped:若容器意外停止,自動重新啟動。
  • 3a2ef06682ac:用於建立容器的映像檔 ID。

現在,驗證資料庫服務是否正在執行:

docker ps

  • 用途: 列出容器。
  • 語法: docker ps [OPTIONS]
[root@novita ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
107b52416c13        3a2ef06682ac        "docker-entrypoint..."   5 minutes ago       Up 5 minutes        0.0.0.0:3306->3306/tcp                                                                       quizzical_mcnulty 

接下來,進入容器內部環境。

docker exec

  • 用途: 在執行中的容器內部執行指令。
  • 語法: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
  • 範例: docker exec -it 107b52416c13 bash
  • 說明: 存取容器 ID 為 107b52416c13 的容器,並執行 bash 指令。

進入容器後,可以像一般 Linux 環境一樣與之互動。使用先前設定的憑證即可存取 MariaDB。

[root@novita ~]# docker exec -it 107b52416c13 bash 
root@107b52416c13:/# mysql -u root -p123456 
Welcome to the MariaDB monitor.  Commands end with ; or \g. 
Your MariaDB connection id is 11 
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
MariaDB [(none)]> 

到目前為止,你已經學會了 Docker 的基礎。試著探索更多吧。

Novita AI 是滿足您 AI 願景的一站式雲端平台。透過無縫整合的 API、無伺服器運算與 GPU 加速,我們提供經濟實惠的工具,幫助您快速建置與擴展 AI 驅動的業務。告別基礎設施的麻煩,免費開始使用——Novita AI 讓您的 AI 夢想成真。