前端工程師眼中的Docker

  • 2020 年 3 月 18 日
  • 筆記

筆者最近在整理 Node.js 操作各資料庫的方法,卻不料遇到一個很棘手的問題:很多資料庫,都需要同時下載 Server 端和 Client 端,並進行相應的配置,著實是麻煩。那有沒有方法可以省去這些步驟呢?

答案肯定是有的,這就是今天要介紹的主題 —— Docker

Docker 概述

Docker 是什麼呢?

通俗地講,當我們部署程式碼到生產伺服器時,第一次都需要先進行環境配置,比如你有 100 台機器,你就要手動配置 100 台伺服器的環境,這樣難保不會出錯。 Docker 則將軟體服務製作成標準化的模板,也就是鏡像,從而實現快捷部署。每次部署新機器,只需要拉取相關鏡像,即可一鍵完成。

Docker 官方提供了很多標準鏡像,涵蓋 MySQLMongoDBNode.js 等常見開源軟體。此外,開發者也可以在已有鏡像的基礎上,打造屬於自己的訂製化鏡像。

接下來以 MySQL 為例,快速入坑 Docker

鏡像和鏡像庫

那麼如何獲取鏡像呢?

Docker 鏡像一般存儲在 鏡像庫 ( registry ) 中。 Docker Hub 和 Docker Cloud 是公共鏡像庫,任何人均可使用。 Docker 默認使用 Docker Hub 。同時,用戶也可以部署自己的私有鏡像庫。

拉取鏡像

首先,從鏡像庫中拉取 MySql 8.0 版本的鏡像:

$ docker pull mysql:8.0

鏡像列表

讀取鏡像列表,驗證 MySQL 鏡像是否拉取成功:

$ docker images  REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE  mysql               8.0                 c8ad2be69a22        3 days ago          465MB

可以看到 MySQL 已經在鏡像列表中,版本號為 8.0

容器

容器 是通過 鏡像 創建的可執行環境,同個鏡像可以實例化多個容器。

創建容器

現在,讓我們使用 MySQL 鏡像創建容器:

$ docker run --name first-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0

命令有點長,且聽我細細講述。

docker run 命令用於創建並執行新容器:--name,用於指定容器名,在此我們將新容器命名為 first-mysql-e ,即 --environment,指定環境變數,MYSQL_ROOT_PASSWORD 環境變數用於配置資料庫 root 用戶的密碼;-d,讓容器在後台運行;最後指定鏡像名和版本號,這裡用的是 mysql:8.0

容器列表

docker ps 命令用於讀取正在運行的容器列表:

$ docker ps  CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES  a68be49896f8        mysql:8.0           "docker-entrypoint.s…"   6 seconds ago       Up 5 seconds        3306/tcp, 33060/tcp   first-mysql

docker ps -a 命令用於讀取所有容器列表,包括停止的容器:

$ docker ps -a  CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                      PORTS                      NAMES  a68be49896f8        mysql:8.0           "docker-entrypoint.s…"   About a minute ago   Up About a minute           3306/tcp, 33060/tcp        first-mysql  c344ce31b67e        mongo:3.6           "docker-entrypoint.s…"   3 months ago         Exited (255) 3 months ago   0.0.0.0:27017->27017/tcp   docker-service_mongo_1

列表中一共有兩個容器,從 STATUS 列可以獲知容器的狀態。first-mysql ,處於運行的狀態;docker-service_mongo_1 處於退出狀態。

停止容器

使用 docker stop 命令停止容器。

$ docker stop a68be49896f8

a68be49896f8first-mysql 的 容器 ID

查看容器列表,發現 first-mysql 容器此時已處於退出狀態:

$ docker ps -a  CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                      NAMES  a68be49896f8        mysql:8.0           "docker-entrypoint.s…"   20 minutes ago      Exited (0) 3 seconds ago                               first-mysql

開啟容器

使用 docker start 開啟已被停止的容器,這裡,我們開啟剛剛被停止的 first-mysql

$ docker start a68be49896f8

查看容器列表,此時 first-mysql 容器已經是運行中狀態。

$ docker ps  CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES  a68be49896f8        mysql:8.0           "docker-entrypoint.s…"   25 minutes ago      Up 6 seconds        3306/tcp, 33060/tcp   first-mysql

在容器內執行命令

掌握了鏡像和容器的基本操作後,接下來,讓我們來看看如何操作 MySQL。我們拉取的 MySQL 鏡像,已經內置了客戶端程式 mysql 命令,可以直接連接並操作 MySQL 。那麼,如何在容器內執行命令呢?

這就要用到 docker exec 命令了:

$ docker exec -it first-mysql bash

這個命令在容器 first-mysql 內執行 bash 命令,啟動一個互動式 Shell 。注意到,命令行參數 -it 表示提供互動式的終端。

執行完上述命令,不出意外,便進入容器 Shell 環境:

root@a68be49896f8:/#

Shell 中,執行 mysql 命令即可連接資料庫:

root@a68be49896f8:/# mysql -u root -p  Enter password:  Welcome to the MySQL monitor.  Commands end with ; or g.  Your MySQL connection id is 9  Server version: 8.0.19 MySQL Community Server - GPL    Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.    Oracle is a registered trademark of Oracle Corporation and/or its  affiliates. Other names may be trademarks of their respective  owners.    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.    mysql>

-u,即用戶名,此處是 root-p,表示密碼,即一開始我們創建容器時指定的密碼。在容器內成功連接資料庫後,就可以愉快地進行各種數據操作了。

容器埠映射

如果我們要在實際中應用 Docker 技術,僅在容器內操作顯然是不夠的。試想一下,當我們需要在本機連接容器內的 MySQL,又該如何操作呢?有辦法將容器的埠映射出來嗎?

先看一下我們的 MySQL 容器都有哪些埠:

$ docker ps  CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES  eff3e64f65bb        mysql:8.0           "docker-entrypoint.s…"   6 minutes ago       Up 6 minutes        3306/tcp, 33060/tcp   first-mysql

可以看到,MySQL 容器暴露了兩個埠,分別是 330633060 ,其中 3306 用於連接資料庫。但遺憾的是,這兩個埠目前還無法被外部訪問,除非將它們映射出來。

創建容器時,可以指定 -p 參數,將本地指定埠映射到容器內:

$ docker run --name first-mysql -e MYSQL_ROOT_PASSWORD=123456 -d -p 3306:3306 mysql:8.0

這個命令在本機開啟 3306 埠,並映射到容器的 3306 埠。

現在,我們再來看下容器發生了什麼變化:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES  e1c17ca83541        mysql:8.0           "docker-entrypoint.s…"   8 seconds ago       Up 6 seconds        0.0.0.0:3306->3306/tcp, 33060/tcp   first-mysql

PORTS 列顯示 0.0.0.0:3306->3306/tcp, 這表示本地 3306 埠映射到容器 3306 埠。0.0.0.0 代表全網可連接。

下載 MySQL 客戶端,連接容器內的 MySQL 伺服器。這裡筆者用的是 Homebrew 下載的 mysql-client。由於本機埠配置了全網可連,所以我們的 host 設定為 127.0.0.1 即可,埠指定 3306。執行如下命令連接 MySQL

$ /usr/local/Cellar/mysql-client/8.0.18/bin/mysql -u root -h 127.0.0.1 -P 3306 -p  Enter password:  Welcome to the MySQL monitor.  Commands end with ; or g.  Your MySQL connection id is 8  Server version: 8.0.19 MySQL Community Server - GPL    Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.    Oracle is a registered trademark of Oracle Corporation and/or its  affiliates. Other names may be trademarks of their respective  owners.    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.    mysql>

成功連接了!

小結

  • Docker 將軟體服務製作成模板,稱為 鏡像
  • 鏡像 存儲在 鏡像庫 中, Docker Hub 和 Docker Cloud 是公共鏡像庫;
  • 通過 鏡像 可快速創建可執行環境,這就是 容器

附錄

更多 Node.js 技術文章,請查看:Node.js小冊 ,轉至 原文 可獲得最佳閱讀體驗。

訂閱更新,獲取更多學習資料,請關注我們的 微信公眾號