在下最近遇到要在伺服器上安裝 Mysql、Nginx、EasyMock 等工具的場景,這裡記錄一下我使用 Docker 安裝的過程,希望也能在類似的場景中幫助到大家~
本文前備知識需要一些 Linux 的一些基本命令,推介先看一下 <半小時搞會 CentOS 入門必備基礎知識> 這篇文章。
CentOS 版本: 7.6
Nginx 版本: 1.16.1
Docker 版本: 19.03.12
你多學一樣本事,就少說一句求人的話
1. 介紹
1.1 出現的原因
前後端開發到測試到生產的過程中,經常會遇到一個問題,明明我在本地跑沒問題,為什麼到測試環境或者生產環境就報錯了了呢,常常這是因為開發、測試、生產的環境與配置不同導致的。
折騰過環境配置的人都明白其中麻煩,換一臺系統、虛擬機器、機器,就又要重來一次,費力費時。由於環境和配置的原因,各種奇奇怪怪因為環境和配置的 Bug,總是像打地鼠遊戲裡面的地鼠一樣不斷冒出來 ?
Docker 對這個問題給出了一個很好的解決方案,通過映象將除了系統之外所需要的系統環境由下而上打包,達到服務跨平臺的無縫運作。也就是說,安裝的時候,把特定的環境一模一樣地搬過來,從而解決「在我的電腦上能跑,在 xx 環境就跑不了」的情況。
另外一個重要的原因,就是輕量,基於容器的虛擬化,Docker 的映象僅包含業務執行所需的 runtime 環境,一個 CentOS/Ubuntu 基礎映象僅 170M,因為輕量一個宿主機可以輕鬆安裝數百個容器。
1.2 是什麼
Docker 是基於 Go 語言實現的雲開源專案,從 2013 年釋出到現在一直廣受關注。Docker 可以讓你像使用集裝箱一樣快速的組合成應用,並且可以像運輸標準集裝箱一樣,儘可能的遮蔽程式碼層面的差異。它將應用程式與該程式的依賴,打包在一個檔案裡面。執行這個檔案,就會生成一個虛擬容器。
程式在這個虛擬容器裡執行,就好像在真實的物理機上執行一樣。有了 Docker,就不用擔心環境問題。
本文就不對比虛擬機器跟 Docker 的區別和優劣了,每個文章都有,說爛了,想了解的話可以百度一下 ?,我這裡就不多說了,下面直接看看怎麼安裝怎麼用起來吧。
2. 安裝 & 配置
2.1 Mac 下安裝
在下直接使用 Homebrew Cask 來安裝,Mac 下:
# Homebrew 安裝
$ braw cask install docker
即可,安裝完輸入命令,直接報錯!
➜ ~ docker
zsh: command not found: docker # 報錯
遇到這個報錯別擔心,安裝完之後要在應用列表裡面雙擊 Docker 應用,輸入密碼之後就可以使用這個命令了 ?。
2.2 CentOS 下安裝
Docker 要求 CentOS 版本必須在 6.5 及以上才可以安裝。
# 安裝
$ sudo yum install yum-utils device-mapper-persistent-data lvm2
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce
# 開啟 Docker
$ sudo systemctl start docker
在 Windows 上可以直接下載安裝包來安裝,或者 Mac 上不使用 Homebrew 也可以去官網直接下載安裝包來安裝,百度一下到處都是安裝方法,其他的就不用多說。
3. 簡單配置並跑起來
3.1 配置映象加速
在 MacOS 的 Docker 配置 Perferences -> Docker Engine
或者 Windows 的 Settings -> Deamon
中的 JSON 中增加一項 registry-mirrors
如下
配置完之後在命令列中 docker info
就可以檢視到我們配置的映象加速地址了。
➜ ~ sudo docker info
...
Registry Mirrors:
https://reg-mirror.qiniu.com/
http://hub-mirror.c.163.com/
https://registry.docker-cn.com/
...
如果你的系統的 Docker 沒有客戶端,比如 CentOS 中,可以直接修改 deamon 配置檔案:
# 修改/建立 docker 的 deamon 配置檔案
$ sudo vi /etc/docker/daemon.json
# 修改為如下配置
{
"experimental": false,
"debug": true,
"registry-mirrors": [
"https://reg-mirror.qiniu.com",
"http://hub-mirror.c.163.com",
"https://registry.docker-cn.com"
]
}
# 修改完 :wq 重啟
$ sudo systemctl restart docker
3.2 Hello World !
然後就可以快樂跑起來我們第一個 Docker 指令 Hello World 了
Good start ! ?
4. 映象 & 容器 & 倉庫
映象和容器的關係就像類和類的例項,一個映象可以同時跑多個容器,單個容器例項又可以建立新的映象。如下圖:
下面解釋一下這個圖裡面出現的元素
概念 | 說明 |
---|---|
Docker 映象 Images | 用於建立 Docker 容器的只讀模板,比如 Ubuntu 16.04系統、Nginx 1.16.0 等,是一個特殊的檔案系統,包括容器執行時需要的程式、庫、資源、引數等,但不包含任何動態資料,內容在構建後也不會被改變,一個映象可以建立多個容器 |
Docker 容器 Container | 容器是獨立執行、相互隔離的一個或一組應用,是映象建立的執行例項,實質是程式,可以看作為一個簡易版的 Linux 環境 + 執行在其中的應用程式 |
Docker 客戶端 Client | 客戶端通過命令列或者其他工具使用 Docker SDK (https://docs.docker.com/devel... 與 Docker 的守護程式通訊 |
Docker 主機 Host | 一個物理或者虛擬的機器用於執行 Docker 守護程式和容器 |
Docker 倉庫 Repository | 集中存放映象檔案的地方,分為公有倉庫和私有倉庫。 |
Docker 註冊伺服器 Registry | 是一個集中儲存、分發映象的服務,官方的叫 Docker Hub。一個 Docker Registry 中可包含多個倉庫,每個倉庫可以包含多個標籤 Tag 的映象,不同的標籤對應不同的版本 |
Docker Machine | Docker Machine 是一個簡化 Docker 安裝的命令列工具,通過一個簡單的命令列即可在相應的平臺上安裝Docker,比如 VirtualBox、 Digital Ocean、Microsoft Azure |
容器的生命週期圖示
容器的五個核心狀態,也就是圖中色塊表示的:Created、Running、Paused、Stopped、Deleted:
- Created:容器已經被建立,容器所需的相關資源已經準備就緒,但容器中的程式還未處於執行狀態。
- Running:容器正在執行,也就是容器中的應用正在執行。
- Paused:容器已暫停,表示容器中的所有程式都處於暫停 ( 不是停止 ) 狀態。
- Stopped:容器處於停止狀態,佔用的資源和沙盒環境都依然存在,只是容器中的應用程式均已停止。
- Deleted:容器已刪除,相關佔用的資源及儲存在 Docker 中的管理資訊也都已釋放和移除。
本文主要關注於使用,就不太贅述這些狀態的切換等,下面直接上手。
5. 基本使用
5.1 操作命令
# 開啟 Docker 開機自啟動
$ sudo systemctl enable docker
# 關閉 Docker 開機自啟動
$ sudo systemctl disable docker
5.2 映象命令
# 去下載映象,先從本地找,沒有去映象,最後沒有去 hub,標籤不寫預設為 lastest
$ docker pull [映象名]:[標籤Tag]
# 列出本機的所有 image 檔案,-a 顯示本地所有映象(包括中間映象),-q 只顯示映象ID,--digests 顯示映象的摘要資訊
$ docker image ls
$ docker images
# 刪除 image 檔案, -f 強制刪除映象
$ docker rmi [映象名][:標籤Tag]
$ docker rmi [映象名1][:標籤Tag] [映象名2][:標籤Tag] # 刪多個
$ docker rmi $(docker ps -a -q) # 刪全部,後面是子命令
# 查詢映象名稱,--no-trunc 顯示完整的映象描述,--filter=stars=30 列出star不少於指定值的映象,--filter=is-automated=true 列出自動構建型別的映象
$ docker search [關鍵字]
# 下載映象,標籤 tag 不寫預設為 lastest,也可以自己加比如 :3.2.0
$ docker pull [映象名][:標籤Tag]
5.3 容器命令
# 列出本機正在執行的容器,-a 列出本機所有容器包括終止執行的容器,-q 靜默模式只顯示容器編號,-l 顯示最近建立的容器
$ docker container ls # 等價於下面這個命令
$ docker ps
# 新建並啟動容器
$ docker run [option] [容器名]
# 啟動容器
$ docker start [容器ID]/[容器Names]
# 重啟容器
$ docker restart [容器ID]/[容器Names]
# 終止容器執行
$ docker kill [容器ID] # 強行終止,相當於向容器裡面的主程式發出 SIGKILL 訊號,那些正在進行中的操作會全部丟失
$ docker kill $(docker ps -a -q) # 強行終止所有容器
$ docker stop [容器ID] # 從容終止,相當於向容器裡面的主程式發出 SIGTERM 訊號,然後過一段時間再發出 SIGKILL 訊號
$ docker stop $(docker ps -a -q) # 終止所有容器
# 終止執行的容器檔案,依然會佔據硬碟空間,可以使用 docker container rm 命令刪除,-f 強制刪除可以刪除正在執行的容器
$ docker rm [容器ID]
$ docker rm `docker ps -aq` # 刪除所有已經停止的容器,因為沒停止的rm刪不了需要加-f
# 檢視容器的輸出,-t加入時間戳,-f跟隨最新日誌列印,--tail數字顯示最後多少條,如果docker run時,沒有使用-it,就要用這個命令檢視輸出
$ docker logs [容器ID]
# 檢視容器程式資訊
$ docker top [容器ID]/[容器Names]
$ docker port [容器ID]/[容器Names]
# 退出容器
$ exit # 容器退出
ctrl + p + q # 容器退出,快捷鍵
# 進入容器
$ docker attach [容器ID] # 退出容器時會讓容器停止,本機的輸入直接輸到容器中
$ docker exec -it [容器ID] # 退出容器時不會讓容器停止,在已執行的容器中執行命令,不建立和啟動新的容器
# 設定容器在docker啟動時自動啟動
$ docker container update --restart=always [容器名字]
這裡要特別說一下 docker run
的 option
,因為最常用:
--name
為容器指定一個名稱;-d
容器啟動後進入後臺,並返回容器 ID,即啟動守護式容器;-P
隨機埠對映;-p 80:8080
將本地 80 埠對映到容器的 8080 埠;bash
容器啟動以後,內部第一個執行的命令。這裡啟動 bash,保證使用者可以使用 Shell;-i
以互動模式執行容器,通常與-t
同時使用;-t
為容器重新分配一個偽輸入終端,容器的 Shell 會對映到當前的 Shell,然後在本機視窗輸入的命令,就會傳入容器,通常與-i
同時使用;--rm
在容器終止執行後自動刪除容器檔案;--restart=always
設定容器自啟動;-v /xxx:/yyy
對映命令,把本機的 xxx 目錄對映到容器中的 yyy 目錄,也就是說改變本機的 xxx 目錄下的內容, 容器 yyy 目錄中的內容也會改變;
比如我在 CentOS 下跑起來一個 CentOS 的 Docker 容器:
# 下載
$ docker pull centos
# 在上面下載的 centos 映象基礎上,新建一個容器名為 mycentos0901 的 centos 例項,並進入這個容器的 bash
$ docker run -it --name mycentos0901 0d120b6ccaa8
[root@169c9fffeecd /] # 進入容器,下面輸入命令,注意這裡 root 後面的一串 ID
$ ls # 可以看到centos的根目錄檔案列表
$ docker # bash: docker: command not found 這個容器沒有安裝docker
是不是很神奇,我們可以在一開始的 CentOS 下面執行 docker ps
來檢視容器列表:
你會發現上面那個 ID,正是下面列表中跑起來的這個容器的 ID,映象的 ID 也是我們前面 pull
下來的 CentOS 映象 ID,名字也是我們起的 mycentos0901
。
如果 docker run
之後報 Conflict. The container name "xxxx" is already in use by container
就直接執行 docker rm $(docker ps -a -q)
刪除已停止的容器,或者精確刪除 docker rm [containerID]
也可以,就可以了。
5.4 幾個常見場景的命令使用
守護式啟動容器
使用 centos
以後臺模式啟動一個容器 docker run -d --name mycentos0903 0d120b6ccaa8
,啟動之後 docker ps -a
檢視,發現容器並不在執行中,這是因為 Docker 的執行機制:Docker 容器後臺執行,必須有一個前臺程式。
容器執行的命令如果不是那些一直掛起的命令,比如 top
、tail
,執行結束會自動退出。所以為了讓容器持續在後臺執行,那麼需要將執行的程式以前臺程式的形式執行。
比如這裡在後臺執行一個命令,這個命令一直在列印 docker run -d centos /bin/sh -c "while true; do echo hello zzyy; sleep 2; done"
,然後我們 logs
檢視一下:
退出容器後對容器操作
退出容器後可以通過 exec
方法對正在執行的容器進行操作:
在容器中拷貝檔案到外部
拷貝檔案使用 cp
命令
$ docker cp [容器ID]/[容器Names]:[要拷貝的檔案目錄] [本機目錄] # 容器檔案拷貝到本機
$ docker cp [本機目錄] [容器ID]/[容器Names]:[要拷貝的檔案目錄] # 本機檔案拷貝到容器
cp
不僅能把容器中的檔案/資料夾拷貝到本機,也可以把本機中的檔案/資料夾拷貝到容器。
演示一下,這裡先到容器裡面建立一個無聊的檔案 xixi.txt
,然後拷貝到本機:
實用的時候,我們可以拷貝配置、日誌等檔案到本地。
6. 安裝 MySQL
# 查詢映象
$ docker search mysql
# 下載映象,實測沒配置映象加速的時候會比較慢,配置了就好一些
$ docker pull mysql
# 檢視映象
$ docker images
# 建立並執行容器
$ docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=888888 -v /Users/sherlocked93/Personal/configs/mysql.d:/etc/mysql/conf.d --name localhost-mysql mysql
稍微解釋一下上面的引數:
-p 3307:3306
將本機的 3307 埠對映到 mysql 容器的 3306 埠,根據需要自行更改;-e MYSQL_ROOT_PASSWORD=<string>
設定遠端登入的 root 使用者密碼;--name <string>
可選,設定容器別名;-v xxx/mysql.d:/etc/mysql/conf.d
將本地目錄下設定資料夾對映到容器的/etc/mysql/conf.d
-v xxx/logs:/logs
將本機指定目錄下的logs
目錄掛載到容器的/logs
-v xxx/data:/var/lib/mysql
將主機制定目錄下的data
目錄掛載到容器的/var/lib/mysql
執行截圖:
然後去 Navicat 中就可以連線到 MySQL 了。
這也太爽了!真的是幾行命令就裝好了啊,比之前真是快樂多了 ?
7. 安裝 Nginx
Nginx 的安裝和其他的類似,如果你還不太瞭解 Nginx 如何使用,可以參看 <Nginx 從入門到實踐,萬字詳解> 這篇文章,看完基本就瞭解如何使用和配置了。
# 查詢/下載映象
$ docker search nginx
$ docker pull nginx
然後建立一個臨時的容器,目的是把預設配置拷貝到本機,我這裡把配置檔案放到 /mnt
目錄下,主要是三個配置資料夾:
/etc/nginx
放置 Nginx 配置檔案;/var/log/nginx/
放置 Nginx 日誌檔案;/usr/share/nginx/html/
放置 Nginx 前端靜態檔案都放在這個資料夾;
分別把這幾個目錄都拷貝到本機的 /mnt
資料夾下的 nginx
、nginx_logs
、html
資料夾。
剛剛建立的臨時容器沒用了 docker rm -f [臨時容器ID]
把臨時容器幹掉,然後 docker run
重新建立 Nginx 容器:
$ docker run -d --name localhost-nginx -p 8082:80 \
-v /mnt/nginx:/etc/nginx \
-v /mnt/nginx_logs:/var/log/nginx \
-v /mnt/html:/usr/share/nginx/html \
--privileged=true nginx
--privileged=true
表示容器內部對掛載的目錄擁有讀寫等特權。
其他配置剛剛上面之前已經講過,應該不用講了。
然後在你自己瀏覽器上就可以訪問了,如果是雲伺服器,記得開放對應埠。
8. 安裝 Easy Mock
因為 Easy Mock 依賴 Redis 和 MongoDB,因此本地環境使用 docker-compose 來搭建 Easy Mock 應該算是最佳實踐了。
安裝 docker-compose
官方文件:https://docs.docker.com/compose/install/
首先你得確定擁有 docker 環境,如果你是 Windows / Mac 使用者,那麼安裝客戶端,就會自帶 docker-compose 了。
因為本次我們是在雲伺服器 CentOS7.6 上搭建,所以我們需要自行安裝 docker-compose,執行如下命令,下載當前穩定版本的 docker-compose
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
修改檔案許可權為可執行檔案
$ sudo chmod +x /usr/local/bin/docker-compose
驗證是否安裝成功
$ docker-compose version
編寫 docker-compose.yml 配置檔案
可以參考官方文件給出的部署文件,也可以參考我下面的配置過程。
首先新建檔案 docker-compose.yml
並將下面 docker-compose 檔案內容複製進入 docker-compose.yml
,然後將內容中註釋位置替換為自己需要的本地地址
version: '3'
services:
mongodb:
image: mongo:3.4.1
volumes:
# /apps/easy-mock/data/db 是資料庫檔案存放地址,根據需要修改為本地地址
- '/apps/easy-mock/data/db:/data/db'
networks:
- easy-mock
restart: always
redis:
image: redis:4.0.6
command: redis-server --appendonly yes
volumes:
# /apps/easy-mock/data/redis 是 redis 資料檔案存放地址,根據需要修改為本地地址
- '/apps/easy-mock/data/redis:/data'
networks:
- easy-mock
restart: always
web:
image: easymock/easymock:1.6.0
# easy-mock 官方給出的檔案,這裡是 npm start,這裡修改為 npm run dev
command: /bin/bash -c "npm run dev:server"
ports:
- 7300:7300 # 改為你自己期望的對映
volumes:
# 日誌地址,根據需要修改為本地地址
- '/apps/easy-mock/logs:/home/easy-mock/easy-mock/logs'
networks:
- easy-mock
restart: always
networks:
easy-mock:
啟動 Easy Mock
在 docker-compose 檔案目錄下,執行如下命令:
$ docker-compose up -d
如果遇到 easymock docker 例項報檔案許可權錯誤
Error: EACCES: permission denied....
要在專案根目錄執行以下命令
$ chmod 777 /yourfile/logs
然後就可以通過瀏覽器上的 你的域名.com:7300
訪問到 easy-mock 了!
如果你覺得域名後面跟著埠號挺難看的,你可以通過配置 Nginx 的二級域名來訪問你部署的 easy-mock,配置二級域名的方法參見 這篇文章
9. 視覺化管理
關於視覺化查詢工具,這裡就簡單推介一個 LazyDocker,由於是在終端執行的,而且支援鍵盤操作和滑鼠點選,就挺騷氣的,有了這個一些查詢語句可以少打幾次了。
安裝比較簡單,執行下面的命令:
$ docker run --rm -it -v \
/var/run/docker.sock:/var/run/docker.sock \
-v ~/.config/lazydocker:/.config/jesseduffield/lazydocker \
lazyteam/lazydocker
可以設定一個終端的 alias
$ alias lzd='docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker lazyteam/lazydocker'
然後你在終端輸入 lzd
就可以瀏覽你的映象、容器、日誌、配置、狀態等等內容了。
10. 結語
由於在下目前使用 Docker 的主要場景是 MySQL、Nginx 之類工具的安裝,所以本文所介紹的內容也大多屬於這個場景。
篇幅原因 Docker 還有一些內容本文沒有介紹,但上面的內容已基本滿足日常的使用,其他 Docker 的內容可以關注一下在下的後續文章~
網上的帖子大多深淺不一,甚至有些前後矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出~
參考文件:
作者其他高贊文章:
PS:本人部落格地址 Github - SHERlocked93/blog,也歡迎大家關注我的公眾號【前端下午茶】,一起加油吧~