手摸手帶你 Docker 從入門到實踐

bg

在下最近遇到要在服務器上安裝 Mysql、Nginx、EasyMock 等工具的場景,這裏記錄一下我使用 Docker 安裝的過程,但願也能在相似的場景中幫助到你們~ html

本文前備知識須要一些 Linux 的一些基本命令,推介先看一下 <半小時搞會 CentOS 入門必備基礎知識> 這篇文章。前端

CentOS 版本: 7.6mysql

Nginx 版本: 1.16.1linux

Docker 版本: 19.03.12nginx

你多學同樣本事,就少說一句求人的話

1. 介紹

1.1 出現的緣由

先後端開發到測試到生產的過程當中,常常會遇到一個問題,明明我在本地跑沒問題,爲何到測試環境或者生產環境就報錯了了呢,經常這是由於開發、測試、生產的環境與配置不一樣致使的。git

折騰過環境配置的人都明白其中麻煩,換一臺系統、虛擬機、機器,就又要重來一次,費力費時。因爲環境和配置的緣由,各類奇奇怪怪由於環境和配置的 Bug,老是像打地鼠遊戲裏面的地鼠同樣不斷冒出來 🐹github

Docker

Docker 對這個問題給出了一個很好的解決方案,經過鏡像將除了系統以外所須要的系統環境由下而上打包,達到服務跨平臺的無縫運做。也就是說,安裝的時候,把特定的環境如出一轍地搬過來,從而解決「在個人電腦上能跑,在 xx 環境就跑不了」的狀況。web

另一個重要的緣由,就是輕量,基於容器的虛擬化,Docker 的鏡像僅包含業務運行所需的 runtime 環境,一個 CentOS/Ubuntu 基礎鏡像僅 170M,由於輕量一個宿主機能夠輕鬆安裝數百個容器。redis

1.2 是什麼

Docker 是基於 Go 語言實現的雲開源項目,從 2013 年發佈到如今一直廣受關注。Docker 可讓你像使用集裝箱同樣快速的組合成應用,而且能夠像運輸標準集裝箱同樣,儘量的屏蔽代碼層面的差別。它將應用程序與該程序的依賴,打包在一個文件裏面。運行這個文件,就會生成一個虛擬容器。sql

程序在這個虛擬容器裏運行,就好像在真實的物理機上運行同樣。有了 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鏡像加速配置

配置完以後在命令行中 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 了

Docker跑起Helloworld

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:

  1. Created:容器已經被建立,容器所需的相關資源已經準備就緒,但容器中的程序還未處於運行狀態。
  2. Running:容器正在運行,也就是容器中的應用正在運行。
  3. Paused:容器已暫停,表示容器中的全部程序都處於暫停 ( 不是中止 ) 狀態。
  4. Stopped:容器處於中止狀態,佔用的資源和沙盒環境都依然存在,只是容器中的應用程序均已中止。
  5. 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 runoption,由於最經常使用:

  1. --name 爲容器指定一個名稱;
  2. -d 容器啓動後進入後臺,並返回容器 ID,即啓動守護式容器;
  3. -P 隨機端口映射;
  4. -p 80:8080 將本地 80 端口映射到容器的 8080 端口;
  5. bash 容器啓動之後,內部第一個執行的命令。這裏啓動 bash,保證用戶可使用 Shell;
  6. -i 以交互模式運行容器,一般與 -t 同時使用;
  7. -t 爲容器從新分配一個僞輸入終端,容器的 Shell 會映射到當前的 Shell,而後在本機窗口輸入的命令,就會傳入容器,一般與 -i 同時使用;
  8. --rm 在容器終止運行後自動刪除容器文件;
  9. --restart=always 設置容器自啓動;
  10. -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 來查看容器列表:

image-20200901225909737

你會發現上面那個 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 容器後臺運行,必須有一個前臺進程

容器運行的命令若是不是那些一直掛起的命令,好比 toptail ,運行結束會自動退出。因此爲了讓容器持續在後臺運行,那麼須要將運行的程序之前臺進程的形式運行。

好比這裏在後臺運行一個命令,這個命令一直在打印 docker run -d centos /bin/sh -c "while true; do echo hello zzyy; sleep 2; done",而後咱們 logs 查看一下:

docker_logs

退出容器後對容器操做

退出容器後能夠經過 exec 方法對正在運行的容器進行操做:

image-20200911142617186

在容器中拷貝文件到外部

拷貝文件使用 cp 命令

$ docker cp [容器ID]/[容器Names]:[要拷貝的文件目錄] [本機目錄]   # 容器文件拷貝到本機
$ docker cp [本機目錄] [容器ID]/[容器Names]:[要拷貝的文件目錄]   # 本機文件拷貝到容器

cp 不只能把容器中的文件/文件夾拷貝到本機,也能夠把本機中的文件/文件夾拷貝到容器。

演示一下,這裏先到容器裏面建立一個無聊的文件 xixi.txt,而後拷貝到本機:

image-20200921210352644

實用的時候,咱們能夠拷貝配置、日誌等文件到本地。

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

稍微解釋一下上面的參數:

  1. -p 3307:3306 將本機的 3307 端口映射到 mysql 容器的 3306 端口,根據須要自行更改;
  2. -e MYSQL_ROOT_PASSWORD=<string> 設置遠程登陸的 root 用戶密碼;
  3. --name <string> 可選,設置容器別名;
  4. -v xxx/mysql.d:/etc/mysql/conf.d 將本地目錄下設置文件夾映射到容器的 /etc/mysql/conf.d
  5. -v xxx/logs:/logs 將本機指定目錄下的 logs 目錄掛載到容器的 /logs
  6. -v xxx/data:/var/lib/mysql 將主機制定目錄下的 data 目錄掛載到容器的 /var/lib/mysql

運行截圖:

安裝Mysql

而後去 Navicat 中就能夠鏈接到 MySQL 了。

這也太爽了!真的是幾行命令就裝好了啊,比以前真是快樂多了 😂

7. 安裝 Nginx

Nginx 的安裝和其餘的相似,若是你還不太瞭解 Nginx 如何使用,能夠參看 <Nginx 從入門到實踐,萬字詳解> 這篇文章,看完基本就瞭解如何使用和配置了。

# 查詢/下載鏡像
$ docker search nginx
$ docker pull nginx

image-20200922203203685

而後建立一個臨時的容器,目的是把默認配置拷貝到本機,我這裏把配置文件放到 /mnt 目錄下,主要是三個配置文件夾:

  1. /etc/nginx 放置 Nginx 配置文件;
  2. /var/log/nginx/ 放置 Nginx 日誌文件;
  3. /usr/share/nginx/html/ 放置 Nginx 前端靜態文件都放在這個文件夾;

分別把這幾個目錄都拷貝到本機的 /mnt 文件夾下的 nginxnginx_logshtml 文件夾。

剛剛建立的臨時容器沒用了 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 表示容器內部對掛載的目錄擁有讀寫等特權。

其餘配置剛剛上面以前已經講過,應該不用講了。

image-20200922204931582

而後在你本身瀏覽器上就能夠訪問了,若是是雲服務器,記得開放對應端口。

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,因爲是在終端運行的,並且支持鍵盤操做和鼠標點擊,就挺騷氣的,有了這個一些查詢語句能夠少打幾回了。

lzd

安裝比較簡單,運行下面的命令:

$ 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 的內容能夠關注一下在下的後續文章~


網上的帖子大多深淺不一,甚至有些先後矛盾,在下的文章都是學習過程當中的總結,若是發現錯誤,歡迎留言指出~

參考文檔:

  1. Empowering App Development for Developers | Docker 官方網站
  2. Docker核心技術(基礎篇)
  3. Docker安裝mysql
  4. Docker文檔
  5. Docker-compose文檔
  6. 使用 docker 運行 easy-mock - 知乎
  7. docker-compose easy-mock - 簡書
  8. 使用 docker 運行 easy-mock | CodingDiary
  9. easymock官方docker倉庫:easy-mock/easy-mock-docker
  10. 使用docker安裝nginx

做者其餘高贊文章:

  1. JS 中能夠提高幸福度的小技巧
  2. Vue 使用中的小技巧
  3. Nginx 從入門到實踐,萬字詳解!
  4. 半小時搞會 CentOS 入門必備基礎知識
  5. 手摸手 Webpack 多入口配置實踐
  6. 前端路由跳轉基本原理

PS:本人博客地址 Github - SHERlocked93/blog,也歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~

相關文章
相關標籤/搜索