docker 使用入門

docker 使用入門

在公司使用微服務以後,由於各個服務之間有依賴關係,調試本身服務的時候每次都須要編譯運行其餘服務,原來使用一臺開發機做爲開發環境的方式就很麻煩,因此考慮用 docker 部署一套能夠複用的開發環境。首先了解下docker的基本使用。html

安裝

點擊連接下載 docker-desktop ,而後傻瓜式安裝。node

安裝好以後能夠在命令行執行 docker --version 命令,查看 docker 是否正常運行。python

教程

官方確定有教程的,因此能夠去官網找一下,我這邊看的是 docker/getting-started 的教程。docker/getting-started 自己就是一個 dockerrepo。下面說一下怎麼看這個教程。mysql

在安裝好 docker 以後,在命令行運行 docker run -d -p 80:80 docker/getting-started 命令, 而後就啓動了一個容器。sql

而後本地瀏覽器訪問 http://localhost/tutorial/ 能夠看到教程。英文的,可是很好理解,有點英語基礎均可以看懂。本篇教程也是按照這個教程來的,記錄下方便之後本身用。docker

接下來只講使用,不講原理。shell

使用

建立第一個本身的APP

教程提供了一個 Node.js 的應用讓咱們直接使用,點擊下載 Node.js APP , 本地的鏈接,上述步驟沒作下載不下來。數據庫

將下載的 zip 文件解壓,用編輯器打開, 這邊我用的是 vscode瀏覽器

建立該APP鏡像

  1. 在下載的 APP 的跟目錄下建立一個名稱爲 Dockerfile 的文件,文件內容以下:
FROM node:12-alpine
RUN apk add --no-cache python g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
  1. APP 跟目錄下運行以下命令:
docker build -t getting-started .

-t 是給鏡像取個名字,名字是 getting-started 。 最後的 . 表明的是運行的是當前目錄下的 Dockerfile 文件。網絡

啓動一個APP容器

  1. 使用 docker run 命令啓動一個容器,啓動的時候要指定使用剛纔構建的鏡像。命令以下:
docker run -dp 3000:3000 getting-started
  1. 啓動以後,在本地瀏覽器輸入 http://localhost:3000 。能夠看到一個 todo list 應用。
  2. 你能夠在應用中使用一下。若是是本身的應用基本就可使用了。

你如今能夠看下下載的 docker-desktop 面板,裏面有兩個容器,一個是用來看教程的,一個是新建立的本身的 APP

更新APP容器

啓動容器後,容器內的應用代碼確定不是一成不變的,加個需求不是很正常的事情嘛,因此須要在更改代碼以後,從新構建鏡像,用新鏡像從新啓動容器。

  1. 修改代碼,在 src/static/js/app.js 文件下更新第 56 行
-                <p className="text-center">No items yet! Add one above!</p>
+                <p className="text-center">You have no todo items yet! Add one above!</p>
  1. 從新構建鏡像
docker build -t getting-started .
  1. 刪除原有容器,不刪除原有容器直接啓動會由於 3000 端口占用啓不起來。能夠用命令刪除,或者直接在 docker-desktop 面板上直接刪除。下面介紹下命令刪除。
  • 首先用命令 docker ps 找到全部啓動的容器。以下圖:
    image.png
  • 圖中第一列就是容器id,而後還用 docker rm <the-container-id> 命令刪除該容器。
  1. 根據新鏡像從新啓動容器,命令以下。
docker run -dp 3000:3000 getting-started
  1. 從新看下應用 http://localhost:3000

持久化數據庫

docker 中每一個容器的文件系統都是獨立的,一個容器沒法訪問到另外一個容器的文件。同一個容器,再重啓後舊容器中的文件就丟了。因此上面的 todo list APP 再容器更新後以前加的 todo 就沒了。那怎麼讓容器更新後還能訪問到以前的數據呢?

這裏引出容器的 volumes 概念。 volumes 會將容器內的目錄映射到宿主機的目錄上,而後每次啓動的時候都加載宿主機的目錄,文件就不會丟了。

有兩種類型的 volumes,一種是 named volumes , 另外一種是 bind mounts

named volumes

首先講一下 named volumes :

  1. 使用 docker volume create 命令建立一個 volume 。
docker volume create todo-db
  1. 刪除已經存在的 todo list APP 容器。步驟上面已經說了。
  2. docker run 命令從新啓動容器,此次啓動要加 -v 參數,命令以下:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started

-v 就是指定 volumes 的意思。

  1. 刷新應用 http://localhost:3000 , 加幾條新的 todo
  2. 而後刪除 APP 容器,從新啓動一個。
  3. 再次刷新應用,確認剛纔的幾條 todo 沒有丟。

注:查看 Valumes 信息命令:

docker volume inspect <valumes name>

bind mounts

而後再來講一下 bind mounts ,它會將宿主機內的目錄與容器內的目錄綁定,而後改變宿主機目錄下的內容,容器內的也會改變,這就能夠實如今宿主機改代碼,及時同步到容器內。使用流程:

  1. 關閉全部的 getting-started 容器。
  2. 運行如下命令:
docker run -dp 3000:3000 \
    -w /app -v "$(pwd):/app" \
    node:12-alpine \
    sh -c "yarn install && yarn run dev"

若是是 PowerShell ,運行以下命令:

docker run -dp 3000:3000 `
    -w /app -v "$(pwd):/app" `
    node:12-alpine `
    sh -c "yarn install && yarn run dev"

命令解釋以下:

  • -dp :是參數 -d ,-p 的縮寫,-d表明後臺運行, -p 指定端口。
  • -w /app :容器內工做目錄,程序運行的目錄。
  • -v "$(pwd):/app" : 這裏指定了 volumes , 將宿主機的當前目錄與容器的 /app 目錄綁定。
  • node:12-alpine :使用的鏡像
  • sh -c "yarn install && yarn run dev" :運行 shell
  1. 用命令 docker logs -f <container-id> 查看日誌,若是你看到如下內容表明啓動成功:
docker logs -f <container-id>
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000
  1. 嘗試着改代碼,將 src/static/js/app.js 文件的 109 行 "Add Item" 改爲 "Add":
-                         {submitting ? 'Adding...' : 'Add Item'}
+                         {submitting ? 'Adding...' : 'Add'}
  1. 刷新網頁看效果。

建立一個多容器的 APP

todo list APP 以前用的是 SQLite Database 來做爲存儲的。如今使用個更通用的,好比 MYSQL。 固然能夠直接把 MYSQLAPP 部署到同一臺機器上,可是 docker 不建議這麼作。 docker 但願每一個容器內的功能單一。因此如今的部署方案是兩個容器,一個部署 MYSQL ,一個部署 APP 。 像這樣:
image.png

這樣兩個容器之間須要經過網絡鏈接。這樣就引出 network 概念。同一個 network 上的容器能夠相互通訊。

建立啓動MYSQL容器

  1. 建立一個 network :
docker network create todo-app
  1. 啓動一個 MYSQL 容器,將該容器鏈接到上一步建立的 network 上面。
docker run -d \
    --network todo-app --network-alias mysql \
    -v todo-mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=todos \
    mysql:5.7

若是用的 PowerShell

docker run -d `
    --network todo-app --network-alias mysql `
    -v todo-mysql-data:/var/lib/mysql `
    -e MYSQL_ROOT_PASSWORD=secret `
    -e MYSQL_DATABASE=todos `
    mysql:5.7

這裏用到了 --network-alias, 該屬性的意思是: 其餘容器鏈接 mysql 填寫 host 的時候,直接填 --network-alias 的值 mysql 就行。至關於域名。

  1. 確認mysql容器是否正常運行
docker exec -it <mysql-container-id> mysql -p

鏈接到mysql以後運行:

mysql> SHOW DATABASES;

能夠看到 todos 庫:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| todos              |
+--------------------+
5 rows in set (0.00 sec)

啓動 APP 容器鏈接到 MYSQL

  1. 關閉全部的 getting-started 容器。
  2. 從新啓動容器
docker run -dp 3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:12-alpine \
  sh -c "yarn install && yarn run dev"

若是是PowerShell :

docker run -dp 3000:3000 `
  -w /app -v "$(pwd):/app" `
  --network todo-app `
  -e MYSQL_HOST=mysql `
  -e MYSQL_USER=root `
  -e MYSQL_PASSWORD=secret `
  -e MYSQL_DB=todos `
  node:12-alpine `
  sh -c "yarn install && yarn run dev"

新增了 --network todo-app 來鏈接到 todo-app 網絡,確保跟 mysql 一個網絡就好。

同時新增了幾個 -e 參數,表明指定要鏈接的mysql的環境變量。

  1. 查看日誌 docker logs <container-id> , 會看到以下內容:
# Previous log messages omitted
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Connected to mysql db at host mysql
Listening on port 3000
  1. 打開網頁 http://localhost:3000 新加幾個 todo
  2. 運行命令鏈接到 mysql :
docker exec -it <mysql-container-id> mysql -p todos

運行以下命令查看是否有新增的數據:

mysql> select * from todo_items;

Docker compose

啓動了 todo listmysql 以後,在 docker-desktop 面板上看到的是兩個容器,可是兩個容器是有聯繫的,會同時啓動和關閉,那該怎麼讓兩個容器聯動起來呢?

這裏就要用到 docker compose ,經過一個 YAML 文件,能夠同時啓動和關閉兩個容器,或者叫一組相關容器。

  1. 在項目的根目錄下建立一個 docker-compose.yml 文件,跟最開始的 Dockerfile 同一目錄下。
  2. 文件內容以下:
version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:
  1. 刪除剛纔建立的 getting-startedmysql 兩個容器。
  2. 在項目根目錄下運行以下命令啓動這組容器:
docker-compose up -d

運行的時候回看到以下輸出:

Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1   ... done
Creating app_mysql_1 ... done

注意到 volumenetwork 都建立了,即便 network 沒有指定。這是由於默認狀況下,compose 會建立一個公共的 network

  1. 接着能夠用 docker-compose logs -f 命令看下日誌。
  2. 刷新下瀏覽器,如今能夠正常使用了。而後能夠觀察下 docker-desktop 面板,能夠看到兩個容器放在了一塊兒。
  3. 而後能夠經過 docker-compose down 命令或者直接在面板上點擊關閉這組容器。

總結

由於要搭建環境,將 docker 官網的內容整理簡化,記錄出image.png

相關文章
相關標籤/搜索