Docker 搭建你的第一個 Node 項目到服務器(完整版)

本文你能學到什麼

做者簡介:koala,專一完整的 Node.js 技術棧分享,從 JavaScript 到 Node.js,再到後端數據庫,祝您成爲優秀的高級 Node.js 工程師。【程序員成長指北】做者,Github 博客開源項目 github.com/koala-codin…javascript

Docker 是什麼

Docker 概念

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

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

Docker 的基本組成架構

看一張 Docker 架構圖java

  1. 左邊大框框是咱們進行 Docker 操做的宿主機,其運行了一個 Docker daemon 的核心守護程序,負責構建、運行和分發 Docker 容器。node

  2. 在宿主機中安裝了 Docker 客戶端,其與 Docker daemon 守護進程進行通訊,客戶端會將 build、pull、run 等命令發送到 Docker daemon 守護進程進行執行。linux

  3. 右框框爲 Docker 註冊表存儲 Docker 鏡像,是一個全部 Docker 用戶共享 Docker 鏡像的服務,Docker daemon 守護進程與之進行交互。nginx

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

Registry

鏡像倉庫,存儲大量鏡像,能夠從鏡像倉庫拉取和推送鏡像。程序員

Docker 鏡像

相似虛擬機快照,從倉庫拉取,或者在現有工具鏡像上建立新鏡像。經過鏡像能夠啓動容器。github

Docker 容器

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

Docker 數據卷

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

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

Docker 網絡

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

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

Docker 應用場景

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

  1. 使用 Koa2 初始化一個 Node 項目,經過 Mongose 中間件 鏈接 Mogodb 數據庫,實現一個基礎接口 Mogodb 插入數據。 項目地址:github.com/koala-codin…

  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 學習):

    • FROM:FROM 是構建鏡像的基礎源鏡像,該 Image 文件繼承官方的 node image。

      詳細說明:Dockerfile 中 FROM 是必備的指令,而且必須是第一條指令! 它引入一個鏡像做爲咱們要構建鏡像的基礎層,就好像咱們首先要安裝好操做系統,才能夠在操做系統上面安裝軟件同樣。

    • RUN:後面跟的是在容器中要執行的命令。

      詳細說明:每個 RUN 指令都會新創建一層,在其上執行這些命令,咱們頻繁使用 RUN 指令會建立大量鏡像層,然而 Union FS 是有最大層數限制的,不能超過 127 層,並且咱們應該把每一層中我用文件清除,好比一些沒用的依賴,來防止鏡像臃腫。

    • WORKDIR:容器的工做目錄

    • COPY:拷貝文件至容器的工做目錄下,.dockerignore 指定的文件不會拷貝

    • EXPOSE:將容器內的某個端口導出供外部訪問

    • 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"] 主進程其實是 shsh 也就結束了,sh 做爲主進程退出了。

    • ENV(補充)

      ENV 指令用來設置環境變量,它有兩種形式:

      ENV <key> <value>
      ENV <key1>=<value1> <key2>=<value2>...
      複製代碼

      定義了環境變量,那麼在後續的指令中,就可使用這個環境變量。

  4. 代碼環節暫且告一段落,將帶有 Dockerfile 提交到 github 或 gitlab等。

    以個人服務器 centos7 爲例,已安裝好 Docker

  5. 首先檢出代碼,把項目克隆到指定目錄

    git clone https://github.com/koala-coding/dockerstudy  
    複製代碼
  6. 進入目錄構建

    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

  7. 經過鏡像 dockerstudy 建立一個容器並運行。

    docker run --name dockerstudycontainer -d -p 3000:3000 dockerstudy  
    複製代碼

    說明:建立的容器名稱是 dockerstudycontainer,你能夠理解爲 pid,這個名稱惟一,建立以後若是不刪除會一直存在。-p 用來指定端口映射,將容器的端口3000映射到主機3000`端口上,這樣就可外部訪問了。

    此時在宿主機中可使用curl測試服務器提供的服務是否正常

    curl localhost:3000
    複製代碼

    或者能夠直接在瀏覽器中請求接口看一下輸出

    建立容器後,有時候須要看一下容器資源佔用,使用docker stats

    docker stats dockerstudycontainer
    複製代碼

    若是是購買的阿里雲或者騰訊雲服務器,注意這裏將本身購買的 centos 服務器3000端口開放,在安全組

  8. 進入容器

    docker ls -a 查看全部容器,包括當前容器的id
    docker exec -it <id> bash
    複製代碼

  9. 日誌檢查 查看運行日誌,「50425b8f2ef3」 爲容器 ID

    $ docker logs -f 50425b8f2ef3
    複製代碼

    可是到了這裏我還有個問題,那我真想看日誌文件的時候,也不能每一個容器進去看日誌,好浪費時間啊!有沒有什麼更高的方式?我會在下一篇文章《線上環境如何優雅的打印,保存,分析日誌》中寫到。

Docker 部署 Mongodb 環境

  1. 遠程獲取 Mongodb 鏡像
docker pull mongo
複製代碼
  1. 建立一個docker容器

    docker run -p 27017:27017 -v /data/db --name docker_mongodb -d mongo
    複製代碼

    在上面的命令中,幾個命令參數的詳細解釋以下:

    • -p 指定容器的端口映射(特殊說明:前面的是本機端口 ,後面的是容器的端口,添加-p參數主動將容器內部端口給暴漏出來,將服務器的 27017 端口映射到容器的 27017 端口,這樣在外網就可經過 服務器的 27017 端口訪問到咱們的服務,Mongodb 默認端口爲 27017。最終訪問的仍是本機的端口)
    • -v 爲設置容器的掛載目錄,這裏是將即本機中的目錄掛載到容器中的/data/db中,做爲 Mongodb 的存儲目錄
    • --name 爲設置該容器的名稱
    • -d 設置容器以守護進程方式運行
  2. 測試鏈接容器中的 Mongodb

可視化工具鏈接

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

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

優雅部署方式 DockerCompose

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

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

Docker 帶來了什麼(優勢)

  • 環境隔離('隔離,安全')

    Docker 實現了資源隔離,一臺機器運行多個容器互無影響。

  • 更高效的資源利用(節約成本)

    Docker 容器的運行不須要額外的虛擬化管理程序的支持,它是內核級的虛擬化,能夠實現更高的性能,同時對資源的額外需求很低。

  • 更快速的交付部署(敏捷)

    使用 Docker,開發人員能夠利用鏡像快速構建一套標準的研發環境,開發完成後,測試和運維人員能夠直接經過使用相同的環境來部署代碼。

  • 更易遷移擴展(可移植性)

    Docker 容器幾乎能夠在任意的平臺上運行,包括虛擬機、公有云、私有云、我的電腦、服務器等,這種兼容性讓用戶能夠在不一樣平臺之間輕鬆的遷移應用。

  • 更簡單的更新管理(高效)

    使用 Dockerfile,只須要不多的配置修改,就能夠替代以往大量的更新工做。而且全部修改都是以增量的方式進行分發和更新,從而實現自動化和高效的容器管理。

Docker的經常使用命令

鏡像經常使用命令

docker pull [鏡像名稱:版本] 拉取鏡像
docker images  鏡像列表
docker rmi [鏡像名稱:版本] 刪除鏡像
docker history [鏡像名稱] 鏡像操做記錄
docker tag [鏡像名稱:版本][新鏡像名稱:新版本]
docker inspect [鏡像名稱:版本] 查看鏡像詳細
docker search [關鍵字] 搜索鏡像
docker login 鏡像登錄
複製代碼

容器經常使用命令

docker ps -a 容器列表(全部容器)
docker ps  查看全部(運行的)容器
docker exec -ti <id> bash  以 bash 命令進入容器內
docker run -ti --name [容器名稱][鏡像名稱:版本] bash 啓動容器並進入
docker logs 查看容器日誌
docker top <container_id> 查看容器最近的一個進程
docker run -ti --name [容器名稱] -p 8080:80 [鏡像名稱:版本] bash  端口映射
docker rm <container_id> 刪除容器
docker stop <container_id> 中止容器
docker start <container_id> 開啓容器
docker restart <container_id> 重啓容器
docker inspect <container_id> 查看容器詳情
docker commit [容器名稱] my_image:v1.0  容器提交爲新的鏡像	
複製代碼

DockerFile經常使用命令

在上面實戰中已經詳細講解,能夠返回看,這裏就再也不重複寫。

總結

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

參考文章

docker node基本配置

docker 網絡模塊

docker基本原理

關注我

  • 歡迎加我微信【coder_qi】,拉你進技術羣,長期交流學習...
  • 歡迎關注「程序員成長指北」,一個用心幫助你成長的公衆號...

Node系列原創文章

深刻理解Node.js 中的進程與線程

想學Node.js,stream先有必要搞清楚

require時,exports和module.exports的區別你真的懂嗎

源碼解讀一文完全搞懂Events模塊

Node.js 高級進階之 fs 文件模塊學習

相關文章
相關標籤/搜索