Docker 搭建你的第一個 Node 項目到服務器


Docker 搭建你的第一個 Node 項目到服務器

Docker


本文你能學到什麼

Docker 搭建你的第一個 Node 項目到服務器

Docker 是什麼

Docker 概念

關於 Docker 的概念是確實不太好總結,下面我通過四點向你說明 Docker 到底是個什麼東西。

  • Docker 是世界領先的軟件容器平臺。
  • Docker 使用 Google 公司推出的 Go 語言 進行開發實現,基於 Linux 內核 的cgroup,namespace,以及 AUFS 類的 UnionFS 等技術,對進程進行封裝隔離,屬於操作系統層面的虛擬化技術。由於隔離的進程獨立於宿主和其它的隔離的進 程,因此也稱其為容器。Docker 最初實現是基於 LXC.
  • Docker 能夠自動執行重複性任務,例如搭建和配置開發環境,從而解放了開發人員以便他們專注在真正重要的事情上,構建傑出的軟件。
  • 用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、複製、分享、修改,就像管理普通的代碼一樣。

Docker 的基本組成架構

看一張 Docker 架構圖

Docker 搭建你的第一個 Node 項目到服務器

  1. 左邊大框框是我們進行 Docker 操作的宿主機,其運行了一個 Docker daemon 的核心守護程序,負責構建、運行和分發 Docker 容器。
  2. 在宿主機中安裝了 Docker 客戶端,其與 Docker daemon 守護進程進行通信,客戶端會將 build、pull、run 等命令發送到 Docker daemon 守護進程進行執行。
  3. 右框框為 Docker 註冊表存儲 Docker 鏡像,是一個所有 Docker 用戶共享 Docker 鏡像的服務,Docker daemon 守護進程與之進行交互。

下面是對架構中基本組成說明,比較詳細,大家看的時候可以對著架構圖看。概念這個東西,你看下就好,怎麼記都記不住的,只有你常用的東西才會記住和想著去記住它,看完本文,可以把下面的應用實踐一遍。

Registry

鏡像倉庫,存儲大量鏡像,可以從鏡像倉庫拉取和推送鏡像。

Docker 鏡像

類似虛擬機快照,從倉庫拉取,或者在現有工具鏡像上創建新鏡像。通過鏡像可以啟動容器。

Docker 容器

從鏡像中創建應用環境,以單進程的方式運行。對外公開服務。是一種短暫的和一次性的環境。

Docker 數據卷

數據卷可以完成數據持久化,數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:

  • 數據卷可以在容器之間共享和重用
  • 對數據卷的修改會立馬生效
  • 對數據卷的更新,不會影響鏡像
  • 卷會一直存在,直到沒有容器使用

Docker 網絡

Docker 容器之間的網絡交互,可以使用端口映射的方式,其他容器可以直接通過端口實現。除該方式外還有一個容器連接(linking)系統也可以達到容器交互。(本文中 node 連接 mongodb 使用的是端口映射的方式)

關於Docker 網絡模塊,容器連接詳情推薦這篇文章:Docker的網絡模式詳解

Docker 應用場景

Docker 部署 Node 項目完整流程(DockerFile實踐)

  1. 使用 Koa2 初始化一個 Node 項目,通過 Mongose 中間件 連接 Mogodb 數據庫,實現一個基礎接口 Mogodb 插入數據。項目地址:https://github.com/koala-coding/dockerstudy
  2. 首先在項目根目錄下創建 .dockerignore 文件,把不需要打包進 Docker Image 裡的文件進行過濾# /usr/src/nodejs/dockerstudy/.dockerignore
    .git
    node_modules
  3. 在項目的根目錄中創建 Dockerfile 文件(Dockerfile 這裡重點講一下)部署 Node項目 的時候,會有一個 Dockerfile 文件配置# /usr/src/nodejs/hello-docker/Dockerfile
    FROM node:10.0
    # 在容器中創建一個目錄
    RUN mkdir -p /usr/src/nodejs/
    # 定位到容器的工作目錄
    WORKDIR /usr/src/nodejs/
    # RUN/COPY 是分層的,package.json 提前,只要沒修改,就不會重新安裝包
    COPY package.json /usr/src/app/package.json
    RUN cd /usr/src/app/
    RUN npm i
    # 把當前目錄下的所有文件拷貝到 Image 的 /usr/src/nodejs/ 目錄下
    COPY . /usr/src/nodejs/
    EXPOSE 3000
    CMD npm start配置參數說明( DockerFile 學習):
  4. FROM:FROM 是構建鏡像的基礎源鏡像,該 Image 文件繼承官方的 node image。詳細說明:Dockerfile 中 FROM 是必備的指令,並且必須是第一條指令!它引入一個鏡像作為我們要構建鏡像的基礎層,就好像我們首先要安裝好操作系統,才可以在操作系統上面安裝軟件一樣。
  5. RUN:後面跟的是在容器中要執行的命令。詳細說明:每一個 RUN 指令都會新建立一層,在其上執行這些命令,我們頻繁使用 RUN 指令會創建大量鏡像層,然而 Union FS 是有最大層數限制的,不能超過 127 層,而且我們應該把每一層中我用文件清除,比如一些沒用的依賴,來防止鏡像臃腫。
  6. WORKDIR:容器的工作目錄
  7. COPY:拷貝文件至容器的工作目錄下,.dockerignore 指定的文件不會拷貝
  8. EXPOSE:將容器內的某個端口導出供外部訪問
  9. CMD:Dockerfile 執行寫一個 CMD 否則後面的會被覆蓋,CMD 後面的命令是容器每次啟動執行的命令,多個命令之間可以使用 && 鏈接,例如 CMD git pull && npm start詳細說明:CMD 指令用來在啟動容器的時候,指定默認的容器主進程的啟動命令和參數。它有兩種形式CMD echo 1
    CMD ["npm", "run", "test"] 必須是雙引號第一種執行的命令會被包裝程,CMD [ "sh", "-c", "echo 1" ] JSON 數組形式,一般推薦 JSON 數組形式。容器中的應用都應該以前臺執行,而不是啟動後臺服務,容器內沒有後臺服務的概念。對於容器而言,其啟動程序就是容器應用進程,容器就是為了主進程而存在的,主進程退出,容器就失去了存在的意義。比如 CMD service nginx start 它等同於 CMD [ "sh", "-c", "service nginx start"] 主進程實際上是 sh,sh 也就結束了,sh 作為主進程退出了。
  10. ENV(補充)ENV 指令用來設置環境變量,它有兩種形式:ENV <value>
    ENV <key1>=<value1> <key2>=<value2>...定義了環境變量,那麼在後續的指令中,就可以使用這個環境變量。/<value2>/<key2>/<value1>/<key1>/<value>
  11. 代碼環節暫且告一段落,將帶有 Dockerfile 提交到 github 或 gitlab等。以我的服務器 centos7 為例,已安裝好 Docker。
  12. 首先檢出代碼,把項目克隆到指定目錄git clone https://github.com/koala-coding/dockerstudy
  13. 進入目錄構建cd dockerstudy
    docker build -t dockerstudy .★build 命令用來製作鏡像,-t 是給鏡像打標籤,-f 參數是指定 Dockerfile 路徑,由於我們使用的是默認 Dockerfile 名稱,所以可以不同填寫該參數。最後一個.也不要省略,表示 Dockerfile 文件的所在目錄, 代表是當前路徑,它指定鏡像構建的上下文。我們剛才說過,真正製作鏡像的是 docker server,當我們執行 build命令時,docker client 會將上下文路徑下的所有內容打包,然後上傳給 docker server。這樣當我們要在 Dockerfile 文件中執行 如 COPY 指令,就可以將上下文中的文件複製到鏡像中去了。”構建目標名稱 dockerstudy,是一個鏡像,可以通過 docker images 來列出所有的鏡像。一般應該會將 Dockerfile 置於一個空目錄下,或者項目根目錄下。如果該目錄下沒有所需文件,那麼應該把所需文件複製一份過來。如果目錄下有些東西確實不希望構建時傳給 Docker引擎,那麼可以用.gitignore 一樣的語法寫一個 .dockerignore。
  14. 通過鏡像 dockerstudy 創建一個容器並運行。docker run --name dockerstudycontainer -d -p 3000:3000 dockerstudy說明:創建的容器名稱是 dockerstudycontainer,你可以理解為 pid,這個名稱唯一,創建之後如果不刪除會一直存在。-p 用來指定端口映射,將容器的端口3000映射到主機3000`端口上,這樣就可外部訪問了。此時在宿主機中可以使用curl測試服務器提供的服務是否正常curl localhost:3000或者可以直接在瀏覽器中請求接口看一下輸出創建容器後,有時候需要看一下容器資源佔用,使用docker statsdocker stats dockerstudycontainer★如果是購買的阿里雲或者騰訊雲服務器,注意這裡將自己購買的 centos 服務器3000端口開放,在安全組”
  15. 進入容器docker ls -a 查看所有容器,包括當前容器的id
    docker exec -it bash
  16. 日誌檢查 查看運行日誌,“50425b8f2ef3” 為容器 ID$ docker logs -f 50425b8f2ef3但是到了這裡我還有個問題,那我真想看日誌文件的時候,也不能每個容器進去看日誌,好浪費時間啊!有沒有什麼更高的方式?我會在下一篇文章《線上環境如何優雅的打印,保存,分析日誌》中寫到。

Docker 部署 Mongodb 環境

  1. 遠程獲取 Mongodb 鏡像
<code>docker pull mongo/<code>
  1. 創建一個docker容器docker run -p 27017:27017 -v /data/db --name docker_mongodb -d mongo在上面的命令中,幾個命令參數的詳細解釋如下:
  2. -p 指定容器的端口映射(特殊說明:前面的是本機端口 ,後面的是容器的端口,添加-p參數主動將容器內部端口給暴漏出來,將服務器的 27017 端口映射到容器的 27017 端口,這樣在外網就可通過 服務器的 27017 端口訪問到我們的服務,Mongodb 默認端口為 27017。最終訪問的還是本機的端口)
  3. -v 為設置容器的掛載目錄,這裡是將即本機中的目錄掛載到容器中的/data/db中,作為 Mongodb 的存儲目錄
  4. --name 為設置該容器的名稱
  5. -d 設置容器以守護進程方式運行
  6. 測試連接容器中的 Mongodb

可視化工具連接

以上是 MongoDB 容器創建後的信息。接下來,我們使用 Robo 3T 圖形界面軟件嘗試打開數據庫。打開 RoBo 3T,選擇新建連接,按照下圖填入相關數據庫信息,保存。

Docker 搭建你的第一個 Node 項目到服務器

注意其中的權限認證。連接數據庫時候可能失敗,會出現問題,這時候注意一個問題,安全組問題,需要把安全組中的27017的 Mongodb 數據庫端口打開

Docker 搭建你的第一個 Node 項目到服務器

優雅部署方式 DockerCompose

Compose 是 Docker 官方開源的一個項目,可以管理多個 Docker 容器組成一個應用,例如 Web 服務,除了服務本身還有數據庫、Redis、Nginx 等一系列相關聯服務需要安裝。

有個 Compose 的支持,我們只需要定義一個 YAML 格式的配置文件(docker-compose.yml),來編寫一個項目所需要的多個容器配置及調用關係,通過簡單的命令即可同時開始或者關閉這些容器。Compose 定位是定義和運行多個 Docker 容器的應用。在這篇文章中不具體講 DockerCompose 使用,主要講清楚 Docker 基本架構各部分的應用,多實踐下哦!

Docker 帶來了什麼(優點)

  • 環境隔離('隔離,安全')Docker 實現了資源隔離,一臺機器運行多個容器互無影響。
  • 更高效的資源利用(節約成本)Docker 容器的運行不需要額外的虛擬化管理程序的支持,它是內核級的虛擬化,可以實現更高的性能,同時對資源的額外需求很低。
  • 更快速的交付部署(敏捷)使用 Docker,開發人員可以利用鏡像快速構建一套標準的研發環境,開發完成後,測試和運維人員可以直接通過使用相同的環境來部署代碼。
  • 更易遷移擴展(
    可移植性)Docker 容器幾乎可以在任意的平臺上運行,包括虛擬機、公有云、私有云、個人電腦、服務器等,這種兼容性讓用戶可以在不同平臺之間輕鬆的遷移應用。
  • 更簡單的更新管理(高效)使用 Dockerfile,只需要很少的配置修改,就可以替代以往大量的更新工作。並且所有修改都是以增量的方式進行分發和更新,從而實現自動化和高效的容器管理。

Docker的常用命令

鏡像常用命令

<code>docker pull [鏡像名稱:版本] 拉取鏡像
docker images 鏡像列表
docker rmi [鏡像名稱:版本] 刪除鏡像
docker history [鏡像名稱] 鏡像操作記錄
docker tag [鏡像名稱:版本][新鏡像名稱:新版本]
docker inspect [鏡像名稱:版本] 查看鏡像詳細
docker search [關鍵字] 搜索鏡像
docker login 鏡像登陸/<code>

容器常用命令

<code>docker ps -a 容器列表(所有容器)
docker ps 查看所有(運行的)容器

docker exec -ti bash 以 bash 命令進入容器內
docker run -ti --name [容器名稱][鏡像名稱:版本] bash 啟動容器並進入
docker logs 查看容器日誌
docker top <container> 查看容器最近的一個進程
docker run -ti --name [容器名稱] -p 8080:80 [鏡像名稱:版本] bash 端口映射
docker rm <container> 刪除容器
docker stop <container> 停止容器
docker start <container> 開啟容器
docker restart <container> 重啟容器
docker inspect <container> 查看容器詳情
docker commit [容器名稱] my_image:v1.0 容器提交為新的鏡像\t/<container>/<container>/<container>/<container>/<container>/<container>
/<code>

DockerFile常用命令

在上面實戰中已經詳細講解,可以返回看,這裡就不再重複寫。

總結

讀完本文後,你應該掌握了 Docker 的基本使用,對 Docker 這個概念不那麼陌生了,並且知道了它的應用場景,可以自己實踐下,這個過程也會出現很多問題的,實踐才能更好的記住那些知識以及常用命令。


作者kaola


分享到:


相關文章: