在公司使用微服務以後,由於各個服務之間有依賴關係,調試本身服務的時候每次都須要編譯運行其餘服務,原來使用一臺開發機做爲開發環境的方式就很麻煩,因此考慮用 docker
部署一套能夠複用的開發環境。首先了解下docker
的基本使用。html
點擊連接下載 docker-desktop ,而後傻瓜式安裝。node
安裝好以後能夠在命令行執行 docker --version
命令,查看 docker
是否正常運行。python
官方確定有教程的,因此能夠去官網找一下,我這邊看的是 docker/getting-started
的教程。docker/getting-started
自己就是一個 docker
的 repo
。下面說一下怎麼看這個教程。mysql
在安裝好 docker
以後,在命令行運行 docker run -d -p 80:80 docker/getting-started
命令, 而後就啓動了一個容器。sql
而後本地瀏覽器訪問 http://localhost/tutorial/
能夠看到教程。英文的,可是很好理解,有點英語基礎均可以看懂。本篇教程也是按照這個教程來的,記錄下方便之後本身用。docker
接下來只講使用,不講原理。shell
教程提供了一個 Node.js
的應用讓咱們直接使用,點擊下載 Node.js APP , 本地的鏈接,上述步驟沒作下載不下來。數據庫
將下載的 zip 文件解壓,用編輯器打開, 這邊我用的是 vscode
。瀏覽器
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"]
APP
跟目錄下運行以下命令:docker build -t getting-started .
-t
是給鏡像取個名字,名字是 getting-started
。 最後的 .
表明的是運行的是當前目錄下的 Dockerfile
文件。網絡
docker run
命令啓動一個容器,啓動的時候要指定使用剛纔構建的鏡像。命令以下:docker run -dp 3000:3000 getting-started
todo list
應用。你如今能夠看下下載的 docker-desktop
面板,裏面有兩個容器,一個是用來看教程的,一個是新建立的本身的 APP
。
啓動容器後,容器內的應用代碼確定不是一成不變的,加個需求不是很正常的事情嘛,因此須要在更改代碼以後,從新構建鏡像,用新鏡像從新啓動容器。
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>
docker build -t getting-started .
3000
端口占用啓不起來。能夠用命令刪除,或者直接在 docker-desktop
面板上直接刪除。下面介紹下命令刪除。docker ps
找到全部啓動的容器。以下圖:docker rm <the-container-id>
命令刪除該容器。docker run -dp 3000:3000 getting-started
docker
中每一個容器的文件系統都是獨立的,一個容器沒法訪問到另外一個容器的文件。同一個容器,再重啓後舊容器中的文件就丟了。因此上面的 todo list APP
再容器更新後以前加的 todo
就沒了。那怎麼讓容器更新後還能訪問到以前的數據呢?
這裏引出容器的 volumes
概念。 volumes
會將容器內的目錄映射到宿主機的目錄上,而後每次啓動的時候都加載宿主機的目錄,文件就不會丟了。
有兩種類型的 volumes
,一種是 named volumes , 另外一種是 bind mounts 。
首先講一下 named volumes :
docker volume create
命令建立一個 volume 。docker volume create todo-db
todo list APP
容器。步驟上面已經說了。docker run
命令從新啓動容器,此次啓動要加 -v
參數,命令以下:docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
-v
就是指定 volumes
的意思。
todo
。APP
容器,從新啓動一個。todo
沒有丟。注:查看
Valumes
信息命令:docker volume inspect <valumes name>
而後再來講一下 bind mounts ,它會將宿主機內的目錄與容器內的目錄綁定,而後改變宿主機目錄下的內容,容器內的也會改變,這就能夠實如今宿主機改代碼,及時同步到容器內。使用流程:
getting-started
容器。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"
:運行 shelldocker 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
src/static/js/app.js
文件的 109 行 "Add Item" 改爲 "Add":- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
該 todo list APP
以前用的是 SQLite Database 來做爲存儲的。如今使用個更通用的,好比 MYSQL
。 固然能夠直接把 MYSQL
跟 APP
部署到同一臺機器上,可是 docker
不建議這麼作。 docker
但願每一個容器內的功能單一。因此如今的部署方案是兩個容器,一個部署 MYSQL
,一個部署 APP
。 像這樣:
這樣兩個容器之間須要經過網絡鏈接。這樣就引出 network 概念。同一個 network 上的容器能夠相互通訊。
docker network create todo-app
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
就行。至關於域名。
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)
getting-started
容器。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
的環境變量。
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
todo
。mysql
:docker exec -it <mysql-container-id> mysql -p todos
運行以下命令查看是否有新增的數據:
mysql> select * from todo_items;
啓動了 todo list
和 mysql
以後,在 docker-desktop
面板上看到的是兩個容器,可是兩個容器是有聯繫的,會同時啓動和關閉,那該怎麼讓兩個容器聯動起來呢?
這裏就要用到 docker compose
,經過一個 YAML
文件,能夠同時啓動和關閉兩個容器,或者叫一組相關容器。
docker-compose.yml
文件,跟最開始的 Dockerfile
同一目錄下。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:
getting-started
和 mysql
兩個容器。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
注意到 volume
和 network
都建立了,即便 network
沒有指定。這是由於默認狀況下,compose
會建立一個公共的 network
。
docker-compose logs -f
命令看下日誌。docker-desktop
面板,能夠看到兩個容器放在了一塊兒。docker-compose down
命令或者直接在面板上點擊關閉這組容器。由於要搭建環境,將 docker
官網的內容整理簡化,記錄出