Docker

簡介

什麼是Docker?

Docker 是一個開源軟體,出現於2013年初,最初是 Dotcloud 公司內部的 Side-Project。
它基於 Google 公司推出的Go語言實作。(Dotcloud 公司後來改名為 Docker)

為什麼要使用Docker?

  • 更有效率的利用資源
  • 統一環境
  • 對於DevOps的好處
  • 使開發高效且可以預測
  • 消除了重複的、平凡的配置任務,在整個開發生命週期中用於快速、簡單和可移植的應用程序開發。
  • Docker 想解決的問題:
    改善傳統虛擬機器因為需要額外安裝作業系統(Guest OS),導致啟動慢、佔較大記憶體的問題。

  • Docker 要提供的解法:
    以應用程式為核心虛擬化,取代傳統需要 Guest OS 的虛擬化技術。

虛擬化技術

虛擬化要解決的問題是:「當我寫了一個程式,在我電腦上可以執行,但在別人電腦上就不行」。

But why?

  • 作業系統不同
  • 硬體配置不同

簡單來說:我的程式可能剛好只跟我的電腦的環境相容。:cry:

何謂虛擬化技術?

而虛擬化要做的就是模擬出一個環境,讓程式可以在不同硬體或作業系統上執行時,都以為自己在同一個環境中執行,以此來避免前面所述的問題。

目前常見用來比較的虛擬化技術有兩種:

  • 在系統層級的虛擬化技術,稱虛擬機器(Virtual machine)
    例如 : Virtual Box 。

    Virtual Box

  • 在作業系統層級技術,此稱容器(Container)
    例如 : Docker 。

    Docker

虛擬機器

以作業系統為中心

傳統虛擬化的目標: 將一個應用程式所需的執行環境打包起來,建立一個獨立環境,方便在不同的硬體中移動。

虛擬機器是在系統層上虛擬化,
簡單來說, Virtual Box 就是一個可以讓你在作業系統(Host OS)上面再裝一個作業系統(Guest OS),然後讓兩個作業系統彼此不會打架的平台。

容器

以應用程式為中心

容器化的目標: 改善虛擬機器因為需要裝 Guest OS 導致啟動慢、佔較大記憶體的問題。

容器是在作業系統層上虛擬化,
透過 Container Manager 直接將一個應用程式所需的程式碼、函式庫打包,
建立資源控管機制隔離各個容器,並分配 Host OS 上的系統資源。
透過容器,應用程式不需要再另外安裝作業系統(Guest OS)也可以執行。

VM vs. CONTAINER

概念

Docker 是一種工具,可用來建立、部署及執行使用容器的應用程式。 容器可讓開發人員封裝含有其所需全部元件 (程式庫、架構、相依性等) 的應用程式,且全部以一個套件的形式出貨

使用容器可確保應用程式會以相同的方式執行,而不管任何自訂的設定或先前在執行該應用程式的電腦 (可能與用來撰寫和測試應用程式程式碼的電腦不同) 上安裝的程式庫。

這可讓開發人員專注於撰寫程式碼,而不需擔心程式碼將在其上執行的系統。

Docker 三元素

要使用 Docker 時最重要的三個元素:
映像檔(Image)、 容器(Container)、 倉庫(Repository)。

用一個簡單的比喻來解釋 :
如果映像檔是一個做蛋糕的模具,容器則是用該模具烤出來的蛋糕,而倉庫是用來集中放置模具們的收納櫃。

Image

  • 映像檔為一個唯獨的模板。
  • 內可包含完整的ubuntu作業系統環境。
  • 映像檔可用來快速生產Docker容器,並可重複產生。
  • 映像檔可以透過(撰寫由命令行構成的)Dockerfile 建立,或是開放公開下載的地方取得。

舉例來說,如果我今天想要一個 node.js 的執行環境跑我寫好的程式,我可以直接到上 Docker Hub 找到相對應的 node.js 映像檔 ,而不需要自己想辦法打包一個執行環境。

  • 它是 Docker 的映像檔主要是一個唯讀的檔案, 是啟動 Docker container 要使用到的檔案。

  • 另外 Docker 的 image 可以像是堆積木一樣, 一層一層的把 Docker image 堆起來。

    如右圖:

Container

  • 容器是由映像檔建立出來的實例。
  • Docker 即是利用容器來執行關鍵技術。
  • 容器可以被啟動、開始、停止、刪除。
  • 且容器與容器之間是相互隔離、保證安全的。

可以把容器看做是一個執行的應用程式加上執行它的簡易版 Linux 環境(包括 root 使用者權限、程式空間、使用者空間和網路空間等)

  • Docker Container 是透過 Docker image 執行起來的 Process,同一個 Docker image 可以啟動多個 Docker Container。

  • Docker container 和 Docker container 之間的環境是隔離開離來的,不會發生 container1 開 8080 的 port,container2 開 8080 的 port 有衝到的問題

Repository

  • 倉庫是集中存放映像檔檔案的場所,每個倉庫中又包含了多個映像檔。
  • 每個映像檔有不同的標籤(tag)。
  • 倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式
  • 而最大的公開倉庫為Docker Hub,裡面存放了大量的現成、實用映像檔供使用者下載。

而 Docker 倉庫註冊伺服器的概念就跟 Github 類似,你可以在上面建立多個倉庫,然後透過 push、pull 的方式上傳、存取。

安裝

Windows

Docker 並非是一个通用的容器工具,它依賴於已存在並運行的 Linux 内核環境。
在 Windows 上部署 Docker 的方法都是先安装一个虛擬機,並在安装 Linux 系統的的虛擬機中運行 Docker。

使用 WSL 在 Windows 上安裝 Linux

開發人員可以在 Windows 電腦上同時存取 Windows 和 Linux 的功能。
Windows 子系統 Linux 版 (WSL) 可讓開發人員直接在 Windows 上安裝 Linux 散發套件 (,例如 Ubuntu、OpenSUSE、Type、Debian、Arch Linux 等) 並使用 Linux 應用程式、公用程式和 Bash 命令列工具,不需要傳統虛擬機器或雙佈設定的額外負荷。

必要條件

您必須Windows 10版本 2004 和更新版本執行, (組建 19041 和更新版本) 或Windows 11。 檢查更新。

安裝 WSL 命令

開啟 PowerShell 或 Windows 命令提示字元(cmd),輸入命令,然後重新開機電腦

wsl --install
  • 啟用選用的 WSL 和虛擬機器平台元件
  • 下載並安裝最新的 Linux 核心
  • 將 WSL 2 設定為預設值
  • 可能需要下載並安裝 Ubuntu Linux 發行版本 (重新開機)
  • 您必須在此安裝程式期間重新開機電腦

若已有其他版本,可以以此指令來下載Ubuntu

wsl --install -d Ubuntu

檢查 WSL 狀態

wsl --status

使用 wsl --install 命令安裝的新 Linux 安裝預設會設定為 WSL 2。

開啟 WSL

wsl.exe

設定 Linux 使用者名稱和密碼

系統會要求您為 Linux 發行版本建立使用者名稱和密碼。

  • 此使用者名稱和密碼是每個各自 Linux 發行版本專屬,不會影響您的 Windows 使用者名稱。
  • 請注意,在輸入 密碼時,畫面上不會顯示任何專案。 這稱為盲目輸入。 您不會看到您輸入的內容,這完全正常。
  • 一旦您建立使用者名稱和密碼,帳戶就會是您散發套件的預設使用者,而且會在啟動時自動登入。
  • 此帳戶將會被視為 Linux 系統管理員,並且能夠執行 sudo (超級使用者執行) 系統管理命令。
  • 在 WSL 上執行的每個 Linux 發行版本都有自己的 Linux 使用者帳戶和密碼。 每當您新增散發套件、重新安裝或重設時,都必須設定 Linux 使用者帳戶。

若要變更或重設密碼,請開啟 Linux 發行版本,然後輸入命令: passwd
系統會要求您輸入目前的密碼,然後要求您輸入新密碼,然後確認您的新密碼。

使用 Docker 設定遠端開發容器

使用 WSL 2 (Windows 子系統 Linux 版 版本 2) 設定適用于 Windows 的 Docker Desktop。

必要條件

  • 安裝 WSL,並為在 WSL 2 中執行的 Linux 發行版本設定使用者名稱和密碼。
  • 安裝Visual Studio Code (選擇性) 。 這會提供最佳體驗,包括能夠在遠端 Docker 容器內撰寫程式碼和偵錯,並聯機到您的 Linux 散發套件。
  • 安裝Windows 終端機 (選擇性) 。 這可提供最佳體驗,包括在同一個介面中自訂和開啟多個終端機的能力, (包括 Ubuntu、Debian、PowerShell、Azure CLI,或任何您想要使用) 。
  • 在 Docker Hub 註冊 Docker 識別碼, (選擇性)

安裝 Docker Desktop

請先到 Docker 官網
https://www.docker.com/docker-windows

在cmd上輸入以下指令可以確認是否下載成功

開啟 Docker Desktop

確定已核取 [設定>一般] 中的 [使用 WSL 2 型引擎]。

移至 [設定>資源>WSL 整合],從您想要啟用 Docker 整合的已安裝 WSL 2 散發套件中選取。

若要確認已安裝 Docker,請開啟 WSL 散發套件 (例如 Ubuntu) ,並輸入下列命令來顯示版本和組建編號: docker --version

使用下列方式執行簡單的內建 Docker 映射,以測試您的安裝是否正常運作:

docker run hello-world

尋找 Docker 映射儲存體資料夾

Docker 會建立兩個散發資料夾來儲存資料:

  • \wsl$\docker-desktop
  • \wsl$\docker-desktop-data

您可以開啟 WSL Linux 發行版本並輸入: explorer.exe .
在 Windows 檔案總管中檢視資料夾,以找到這些資料夾。
輸入: \\wsl$

基礎指令

Image 映像檔 常用指令

Container 容器 常用指令

Registry 倉庫 常用指令

基礎指令實作

實作目標:

  1. 先從 Docker Hub 上把 Ubuntu OS 的 image pull 到 local,
  2. 有了 image 之後就可以把 Docker container 執行起來,
  3. 然後進入到 container 裡面安裝和啟動 Apache 的 HTTP Service,
  4. 並且寫一個有 HelloWorld 字串的 HTML 檔案。
  5. 最後使用 Browser 連到 Docker Container 裡面的 HTTP Service,
  6. 確認 HelloWorld 的字串能正常的顯示出來。

實作的流程如下:

  1. 從 Docker Hub 下載 Docker Image 到 local
  2. 使用 Docker Image 啟動 Docker Container 並進入 Docker Container的terminal
  3. 在 Docker Container 裡面安裝 Apache 的 HTTP Service,並且寫一個 helloworld 的 html 檔
  4. 使用 Browser 連到 helloworld.html 確認 Docker Container 有成功的被啟動起來

第一步:

從 Docker Hub 下載 Docker Image 到 local

  1. 要下載 Docker Image 之前需要先搜尋一下,Docker Image 的 Name 是什麼,指令如下:

    ​​​​$ docker search ubuntu -f is-official=true
    

    is-official=true 表示要搜尋是官方的 Docker image

    就選擇星星數最多的 Name 為 ubuntu

  2. 找到了 ubuntu 的 Docker Image Name 之後,就可以把此 image pull 下來,指令如下:

    ​​​​$ docker pull ubuntu
    

    執行結果如下圖

  3. 要再一次確認 ubuntu 的docker image有沒有下載下來,可以使用以下的指令

    ​​​​$ docker images
    

    執行結果如下圖

第二步:

有了 Docker Image 之後就可以把 container 執行起來了,並且進入 Docker Container 的 terminal 裡面

  1. 指令如下

    ​​​​$ docker run -it -p 8000:80 ubuntu /bin/bash 
    

    使用以上的指令就可以進入了docker container 裡面的 terminal

  2. 可以再打開另外一個terminal視窗,輸入以下指令

    ​​​​$ docker ps -a
    

    確認 docker container 有正常的執行,如下圖:


在要離開 docker container 的 terminal 時有一個坑。就是如果輸入 exit 指令時,container 會被關閉,如下圖:

如果不要停止 container 而要退出 docker container 的terminal 需要輸入 ctrl + p 之後再輸入 ctrl + q 的按鍵,就不會把 container 關閉。

第三步:

  1. 在 docker container 裡面安裝和啟動 apache 的 http service,指令如下:

    ​​​​root@a03f4fc98ea2:/# apt-get update
    ​​​​root@a03f4fc98ea2:/# apt-get install -y apache2
    ​​​​root@a03f4fc98ea2:/# service apache2 start
    

    if it is success will show

  2. 簡單寫一個 hellowolrd.html檔案放在 /var/www/html 的路徑下,指令如下:

    ​​​​root@a03f4fc98ea2:/# echo "HelloWorld" > /var/www/html/helloworld.html
    
  3. 使用 cat /etc/hosts 指令查看 docker container 的 IP 如下圖:

  4. 如果想要使用 ifconfig 指令,需要安裝 net-tools 工具指令如下:

    ​​​​root@a03f4fc98ea2:/# apt-get install -y net-tools
    

第四步:

使用 Linux 虛擬機GUI browser 輸入 http://172.17.0.2/helloworld.html 的 URL 查看 helloworld.html 的檔案是否能正常的顯示。

使用 Window 本機的 browser 輸入 http://localhost:8000/helloworld.html 的 URL 查看 helloworld.html 的檔案是否能正常的顯示,畫面如下:

Dockerfile

Dockerfile 由一行行命令語句組成,並且支援以 # 開頭的註解行。

Dockerfile 分為四部分:

  • 基底映像檔資訊
  • 維護者資訊
  • 映像檔操作指令
  • 容器啟動時執行指令。
# This dockerfile uses the ubuntu image 
# VERSION 2 - EDITION 1 # Author: docker_user 
# Command format: Instruction [arguments / command] .. 

# 基本映像檔,必須是第一個指令 
FROM ubuntu

# 維護者: docker_user <docker_user at email.com> (@docker_user) 
MAINTAINER docker_user docker_user@email.com 

# 更新映像檔的指令 
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list 
RUN apt-get update && apt-get install -y nginx 
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf 

# 建立新容器時要執行的指令 
CMD /usr/sbin/nginx

Dockerfile 基本語法

Example

FROM centos:7
MAINTAINER jack

RUN yum install -y wget

RUN cd /

ADD jdk-8u152-linux-x64.tar.gz /

RUN wget http://apache.stu.edu.tw/tomcat/tomcat-7/v7.0.82/bin/apache-tomcat-7.0.82.tar.gz
RUN tar zxvf apache-tomcat-7.0.82.tar.gz

ENV JAVA_HOME=/jdk1.8.0_152
ENV PATH=$PATH:/jdk1.8.0_152/bin
CMD ["/apache-tomcat-7.0.82/bin/catalina.sh", "run"]

FROM: 使用到的 Docker Image 名稱,今天使用 CentOS

MAINTAINER: 用來說明,撰寫和維護這個 Dockerfile 的人是誰,也可以給 E-mail的資訊

RUN: RUN 指令後面放 Linux 指令,用來執行安裝和設定這個 Image 需要的東西

ADD: 把 Local 的檔案複製到 Image 裡,如果是 tar.gz 檔複製進去 Image 時會順便自動解壓縮。Dockerfile 另外還有一個複製檔案的指令 COPY 未來還會再介紹

ENV: 用來設定環境變數

CMD: 在指行 docker run 的指令時會直接呼叫開啟 Tomcat Service

Dockerfile 實作

已經體驗過使用 Docker 的指令,把 Docker Image Pull 到 local,並且執行 container,然後在 container 上安裝 HTTP Service,就類似是在使用 VM。

直接進入 Docker Container 裡面下一些指令安裝程式和改設定檔,不夠自動化,可能需要常常的重覆在做同一件事,這樣會很沒效率。

寫 Dockerfile,只要下 docker build 的指令就可以把 Docker Image 建構起來,未來要使用就直接 Run 此 Image。

實作目標:

  1. 要做到在 Dockerfile 裡面,撰寫安裝 Java 和 Tomcat 的指令,包成 Docker Image,
  2. 之後只要呼叫到 docker run 指令,就可以把 Tomcat Service 啟動起來。

主要目的用來體驗如何撰寫 Dockerfile 和 Build Image 以及執行 Docker container。

記住要使用 WSL2 此虛擬機 來實作 Docker

可參考前面 安裝 Windows,或以下訊息

Docker 並非是一个通用的容器工具,它依賴於已存在並運行的 Linux 内核環境。
在 Windows 上部署 Docker 的方法都是先安装一个虛擬機,並在安装 Linux 系統的的虛擬機中運行 Docker。

第一步:

建立 Dockerfile

  1. 建立寫 Dockerfile 會用到的資料夾,指令如下

    ​​​​$ mkdir docker-test
    ​​​​$ cd docker-test
    
  2. 下載JDK 的安裝檔放在 docker-test資料夾裡,使用的版本是 jdk-19.0.2

    下載連結
    https://download.java.net/java/GA/jdk19.0.2/fdb695a9d9064ad6b064dc6df578380c/7/GPL/openjdk-19.0.2_linux-x64_bin.tar.gz

    ​​​​sudo apt install
    

    將檔案移至路徑 \wsl$\Ubuntu\home\[user name]\docker-test

  3. 撰寫Dockerfile

    ​​​​$ vi Dockerfile
    

    Dockerfile 的內容如下

    ​​​​FROM centos:7
    ​​​​MAINTAINER HsingYu
    ​​​​
    ​​​​# 安裝 wget,yum 是 centos 的安裝指令
    ​​​​RUN yum install -y wget
    
    ​​​​RUN cd /
    ​​​​
    ​​​​# 加入 jdk-19.0.2 壓縮檔案,加入後會自動解壓縮
    ​​​​ADD openjdk-19.0.2_linux-x64_bin.tar.gz /
    
    ​​​​# 下載 apache-tomcat-10.1.7.tar.gz
    ​​​​RUN wget --no-check-certificate https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.7/bin/apache-tomcat-10.1.7.tar.gz
    ​​​​# 解壓縮 apache-tomcat-10.1.7.tar.gz
    ​​​​RUN tar zxvf apache-tomcat-10.1.7.tar.gz
    ​​​​
    ​​​​# 設置 java 的環境變數
    ​​​​ENV JAVA_HOME=/jdk-19.0.2
    ​​​​ENV PATH=$PATH:/jdk-19.0.2/bin
    ​​​​CMD ["/apache-tomcat-10.1.7/bin/catalina.sh", "run"]
    
  4. 撰寫完 Dockerfile 之後資料夾的結構如下圖

或者將下載 jdk19.0.2 也寫入 dockerfile

FROM centos:7
MAINTAINER HsingYu

RUN yum install -y wget

RUN cd /

RUN wget https://download.java.net/java/GA/jdk19.0.2/fdb695a9d9064ad6b064dc6df578380c/7/GPL/openjdk-19.0.2_linux-x64_bin.tar.gz
RUN tar zxvf openjdk-19.0.2_linux-x64_bin.tar.gz

RUN wget --no-check-certificate https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.7/bin/apache-tomcat-10.1.7.tar.gz
RUN tar zxvf apache-tomcat-10.1.7.tar.gz

ENV JAVA_HOME=/jdk-19.0.2
ENV PATH=$PATH:/jdk-19.0.2/bin
CMD ["/apache-tomcat-10.1.7/bin/catalina.sh", "run"]

第二步:

Build Docker Image

  1. 預設在和 Dockerfile 檔案同層的資料夾底下輸入, docker build 指令,如下

    ​​​​$ docker build -t mytomcat . --no-cache
    

    使用 no-cache 的主要原因,是避免在 Build Docker image 時被 cache 住,而造成沒有 build 到修改過的 Dockerfile。

    Build 完的結果如下圖:

  2. Build 完 Docker Image 之後,使用 docker images 指令查看是否有 build 成功如下圖

第三步:

在 Build 完 Docker Image 之後就可以執行 Docker Container,這時Tomcat 的 Service 也會跟者被執行起來,指令如下

在瀏覽器跑

$ docker run -p 8080:8080 mytomcat

在虛擬機跑

$ docker run mytomcat

Tomcat Service 會被執行起來的主要原因是在 Dockerfile 裡面有寫 CMD 指令,呼叫啟動 Tomcat Service

第四步:

打開 Browser 確認

  • 要打開 Browser 確認 Tomcat Service 有沒有被執行起來時,發現我們不知道 Docker Container 的 IP,這時侯只能使用 docker exec 進入 docker container查詢 IP 。

要使用 docker exec 指令之前需要先知道 Container 的 ID 所以需要先使用 docker ps 指令查詢 Container ID,如下圖:

  • 有了 IP 之後就可以打開 Browser 輸入 http://172.17.0.2:8080 URL的位置,確認 Tomcat Service 是否有啟動,如下圖:

直接進入 Docker Container 去看 IP 的位址其實有點麻煩,會故意這樣 Daemon 主要的原因,是讓大家了解到我們把 Docker Container 執行啟來時並不會知道它的 IP 位址在哪,這需要透過設定有關於 Docker 的 Network 來解決這個問題。

目前使用最簡單的方法,就是在run docker container 時用 Port 的 Mapping 來解決此問題,重新再一次 run docker container,指令如下:

$ docker run -p 8080:8080 mytomcat

Container 的 8080 port mapping到 localhost 的 8080 port ,這樣只要輸入 http://localhost:8080 就可以看到 tomcat service 的 WebUI 畫面了。

Docker Compose

為什麼要用 Docker Compose?

  1. 之前有介紹過使用 docker run 指令就可以把 Docker Container 啟動起來,但是如果我們要啟動很多個 Docker Container 時,就需要輸入很多次 docker run 指令。
  2. 另外 container 和 container 之間要做關聯的話也要記得它們之間要如何的連結(link) Container,這樣在要啟動多個 Container 的情況下,就會顯得比較麻煩。

如何運作?

Docker-Compose: 寫一個 docker-compose.yml,把所有要使用 Docker Image 寫上去,也可以把 Container 之間的關係連結(link)起來。

最後只要下 docker-compose up 指令,就可以把所有的 Docker Container 執行起來,這樣就可以很快速和方便的啟動多個 container。

Docker Compose 常用指令

# 啟動所有的 Docker Container

$ docker-compose up

# 查看 Docker Container 的執行狀態

$ docker-compose ps

# 看執行的 log

$ docker-compose logs

# 停止 docker-compose 執行的所有 Container

$ docker-compose stop

# 刪除 docker-compose 的所有 Container

$ docker-compose rm

Docker Compose 實作

  1. 實作的部份主要就是要把 Docker-Compose 安裝起來
  2. 然後撰寫一個 docker-compose.yml
  3. 並且使用 docker-compose up,指令把所有的 Docker Container 啟動起來

安裝 Docker-Compose

# cd /usr/bin
# wget https://github.com/docker/compose/releases/download/1.18.0/docker-compose-Linux-x86_64
# mv docker-compose-Linux-x86_64 docker-compose
# chmod 755 docker-compose

撰寫 docker-compose.yml

version: '2'
services:
  db:
     image: mysql
     environment:
        MYSQL_ROOT_PASSWORD: 123456
  admin:
     image: adminer
     ports:
       - 8080:8080

主要的功能是要啟動 2 個 Docker Container,一個是 mysql 的 Container,另外一個是 admin 管理 mysql Web UI 的 container

MYSQL_ROOT_PASSWORD 的環境變數用來設定登入 mysql 的密碼

參考網站: https://hub.docker.com/_/mysql/

啟動所有的 Docker Container

$ docker-compose up -d
  • -d 參數代表要執行在背景的方式

查看 Docker Container 的執行狀態

$ docker-compose ps

admin 執行

http://localhost:8080


Wed, Feb 1, 2023 3:51 AM

HsingyuChen