前端工程師學Docker?看這篇就夠了
傳統的虛擬機,非常耗費性能
Docker可以看成一個高性能的虛擬機,并且不會浪費資源,主要用于Linux環境的虛擬化,類似VBox這種虛擬機,不同的是Docker專門為了服務器虛擬化,并支持鏡像分享等功能。前端工程師也可以用于構建代碼等等。
目前看,Dokcer不僅帶火了GO語言,還會持續火下去。
首先,我們看看傳統的虛擬機和Docker的區別。
傳統的虛擬機:
Docker:
可以看到,傳統的虛擬機是每開一個虛擬機,相當于運行一個系統,這種是非常占用系統資源的,但是Docker就不會。但是也做到了隔離的效果
Docker容器虛擬化的優點:
- 環境隔離
Docker實現了資源隔離,實現一臺機器運行多個容器互不影響。
2. 更快速的交付部署
使用Docker,開發人員可以利用鏡像快速構建一套標準的研發環境,開發完成后,測試和運維人員可以直接通過使用相同的環境來部署代碼。
3. 更高效的資源利用
Docker容器的運行不需要額外的虛擬化管理程序的支持,它是內核級的虛擬化,可以實現更高的性能,同時對資源的額外需求很低。
4. 更易遷移擴展
Docker容器幾乎可以在任意的平臺上運行,包括烏力吉、虛擬機、公有云、私有云、個人電腦、服務器等,這種兼容性讓用戶可以在不同平臺之間輕松的遷移應用。
5. 更簡單的更新管理
使用Dockerfile,只需要小小的配置修改,就可以替代以往的大量的更新工作。并且所有修改都是以增量的方式進行分發和更新,從而實現自動化和高效的容器管理。
正式開始
本文撰寫于2019年10月13日
電腦系統:Mac OS
使用最新版官網下載的Docker
以下代碼均手寫,可運行
下載官網的Docker安裝包,然后直接安裝
Docker官網下載地址
安裝后直接打開
打開終端命令行,輸入docker,會出現以下信息,那么說明安裝成功。
下載安裝成功后,首先學習下Docker的兩個核心知識點
container(容器)和image(鏡像)
Docker的整個生命周期由三部分組成:鏡像(image)+容器(container)+倉庫(repository)
思維導圖如下:
該如何理解呢?
每臺宿主機(電腦),他下載好了Docker后,可以生成多個鏡像,每個鏡像,可以創建多個容器。發布到倉庫時,以鏡像為單位。可以理解成:一個容器就是一個獨立的虛擬操作系統,互不影響,而鏡像就是這個操作系統的安裝包。想要生成一個容器,就用安裝包(鏡像)生成一次
上面就是Docker的核心概念,下面開始正式操作
補充一點:如果想深入Docker , 還是要去認真學習下原理,今天我們主要講應用層面的
首先,我們回到終端命令行操作
輸入:
- docker images
如果你的電腦上之前有創建過的鏡像,會得到如下:
如果沒有的話就是空~
我們首先創建一個自己的鏡像
先編寫一個Node.js服務
創建index.js
- // index.js
- const Koa = require('koa');
- const app = new Koa();
- app.use(async ctx => {
- ctx.body = 'Hello docker';
- });
- app.listen(3000);
然后配置package.json文件
- {
- "name": "app",
- "version": "1.0.0",
- "private": true,
- "scripts": {
- "start": "node server.js"
- },
- "dependencies": {
- "koa": "^2.5.0"
- }
- }
正常情況下 使用
npm start 或 node index.js 就可以啟動服務
可是我們這里需要打包進Docker中,這里就需要寫一個配置文件dockerfile
vsCode有天然插件支持
在目錄下新建文件dockerfile,加入如下配置
- FROM node
- ADD . /app/
- EXPOSE 3000
- WORKDIR /app
- RUN npm install
- CMD ["node","./index.js"]
解釋一下,上面這些配置的作用
FROM 是設置基礎鏡像,我們這里需要Node
ADD是將當前文件夾下的哪些文件添加到鏡像中 參數是 [src,target]
這里我們使用的 . 意思是所有文件,當然跟git一樣,可以配置ignore文件
EXPOSE是向外暴露的端口號
WORKDIR是說工作目錄,我們這里將文件添加到的是app目錄,所以配置app目錄為工作目錄,
這樣就不用在命令行前面加/app了
RUN是先要執行的腳本命令
CMD是執行的cmd命令
可以想一想,我們打包好鏡像后,然后啟動鏡像會發生什么?
文件編寫完,使用命令打包鏡像
使用命令打包已經好的文件目錄
- docker image build ./ -t app
打包后出現提示:
此時我們查看Docker鏡像,使用命令:
- docker images
我們可以清楚看到,app鏡像已經打包成功,下面我們啟動它
- docker run -p 8000:3000 app
使用上面命令即可啟動我們的鏡像,這時我們在命令中輸入
- curl 127.0.0.1:8000
得到返回內容
Hello docker
瀏覽器輸入: 127.0.0.1:8000 即可訪問到頁面~
以上說明,我們的第一個Docker鏡像已經制作成功
有人可能會覺得到這里,鏡像和容器有點混淆了,不是先有鏡像再有容器嗎?
其實是我們啟動的鏡像有腳本命令幫我們啟動了服務,于是Docker幫我們自動創建了容器
查看Docker容器命令:
- docker ps -a 列出所有容器
- 不加 -a 僅列出正在運行的,像退出了的或者僅僅只是創建了的就不列出來
- docker container ls 列出當前運行的容器
輸入上面 docker container ls
得到結果
原來Docker看我們啟動了腳本服務,幫我們自動生成了容器?
下面我們來一個生成鏡像,再生成容器,最后手動啟動容器的例子
這次我們配置,加入Nginx反向代理服務器
首先,創建用戶需要看到的html文件
這里我們給一個普通的 hello-world內容的index.html文件即可
然后創建dickerfile文件,配置如下,將index.html文件添加到對應的位置
- FROM nginx
- COPY ./index.html /usr/share/nginx/html/index.html
- EXPOSE 80
對外暴露端口號80
這里特別提示:配置文件怎么寫,根據你的基礎鏡像來,百度基本都能找到,不用糾結這個
此時的文件結構:
老規矩,開始打包
- docker build ./ -t html
打印信息:
輸入終端命令:
- docker images
得到結果:
新的鏡像html已經構建成功,但是此時查看容器,是沒有正在運行的
輸入命令:
docker container ls //查看正在運行的所有容器
docker container ls -a //查看所有容器
得到結果是:
可以確認的是,我們創建鏡像不會自動生成和啟動容器
我們手動生成容器
- docker container create -p 8000:80 html
此時命令行返回 一段值
輸入
- docker container ls
沒有顯示有任何啟動的容器,這時候我們手動啟動
輸入
- docker container start ***(上面那段值)
再重復 docker container ls 命令
得到結果
此時訪問localhost:8000即可正常訪問頁面~
至此,我們可以確定,創建鏡像只要不啟動,不會生成容器,更不會運行容器
那怎樣將Docker用在前端的日常構建中呢?
我們使用gitHub+travis+docker來形成一套完整的自動化流水線
只要我們push新的代碼到gitHub上,自動幫我們構建出新的代碼,然后我們拉取新的鏡像即可(gitLab也有對應的代碼更新事件鉤子,可以參考那位手動實現Jenkens的文章)
首先我們先進入 Travis CI 官網配置,注冊綁定自己的gitHub賬號
然后在左側將自己需要git push后自動構建鏡像的倉庫加入
接著在項目根目錄配置 .travis.yml 文件
- language: node_js
- node_js:
- - '12'
- services:
- - docker
- before_install:
- - npm install
- - npm install -g parcel-bundler
- script:
- - parcel build ./index.js
- - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- - docker build -t jinjietan/mini-react:latest .
- - docker push jinjietan/mini-react:latest
每次更新push代碼,都會下載,然后執行打包命令,這樣你下載的鏡像就是有最新的代碼。不再需要每個人下載打開鏡像再去build
為了降低復雜度,這里使用了Parcel打包工具,零配置
更改dockerfile內容,將parcel打包后的內容COPY進容器
- FROM nginx
- COPY ./index.html /usr/share/nginx/html/
- COPY ./dist /usr/share/nginx/html/dist
- EXPOSE 80
添加好了你的庫之后,選擇這里的設置
然后添加兩個環境變量:
DOCKER_USERNAME和DOCKER_PASSWORD
這里,我將我編寫的mini-react框架源碼,放入docker中,然后使用parcel打包工具打包,再用nginx反向代理~
特別提示:這里的Docker容器,想要后臺運行,就必須有一個前臺進程。容器運行的命令如果不是那些一直掛起的命令(比如tcp,ping),就是會自動退出的
通過 docker ps -a 可以看到容器關閉的原因
注意 :jinejietan/mini-react應該換成你的用戶名/包名,再push代碼
這是思維導圖:
當配置成功,代碼被推送到gitHub上后,travis-ci幫我們自動構建發布新鏡像
一定要學會使用: docker ps -a 查看容器的狀態
成功的提示:
至此,發布,自動構建鏡像已經完成
正式開始拉取鏡像,啟動容器
我們剛才發布的鏡像名稱是:jinjietan/mini-react
先使用下面幾條命令
- docker中 啟動所有的容器命令
- docker start $(docker ps -a | awk '{ print $1}' | tail -n +2)
- docker中 關閉所有的容器命令
- docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)
- docker中 刪除所有的容器命令
- docker rm $(docker ps -a | awk '{ print $1}' | tail -n +2)
- docker中 刪除所有的鏡像
- docker rmi $(docker images | awk '{print $3}' |tail -n +2)
- tail -n +2 表示從第二行開始讀取
清除當前宿主機上面所有的鏡像,容器,依次執行
然后使用:
- docker image pull jinjietan/mini-react:latest
拉取鏡像,這時候需要下載
拉取完成后,使用
- docker images
可以看到jinjietan/mini-react:latest鏡像已經存在了
我們使用
- docker container create -p 8000:80 jinjietan/mini-react:latest
創建這個鏡像的容器,并且綁定在端口號8000上
最后輸入下面的命令,即可啟動mini-react框架的容器
- docker container start ***(上面create的返回值)
瀏覽器輸入 127.0.0.1:8000 發現,訪問成功,框架生效。
Docker的使用,我們大致就到這里,個人認為,用Docker比不用好,這個技術已經快跟TypeScript一樣,到不學不行的階段了。
并不是說你非要用它,而是比如說,你如果不怎么懂TypeScript,你就沒辦法把如今那些優秀庫的大部門的源碼搞得那么清楚。
越來越多的技術在依賴Docker
當然,其實這個mini-react框架源碼也是不錯的,如果有興趣可以了解以下,源碼都在:
mini-react框架+鏡像配置源碼,記得切換到diff-async分支哦~

















































