30分鐘帶你瞭解Web工程師必知的Docker知識

前言

筆者以前和朋友一直在討論web技術方向的話題,也一直想了解web運維方面的知識,因此特地請教了一下個人朋友老胡,他對web運維和後端技術有很是多的實戰經驗,因此在本文中他也提供了很多幫助。本文主要會介紹Docker的基礎知識和應用領域,並經過實際部署一個web項目來帶你們瞭解Docker的使用方式。javascript

做爲一名前端工程師,爲何要學習Docker呢?首先筆者先來介紹一下Dockercss

Docker 是一個基於 Go 語言開發的開源應用容器引擎, 可讓咱們把咱們的應用和包打包到一個輕量級、可移植的容器中,而後發佈到任何流行的 Linux 機器上,而且能夠實現虛擬化。所謂容器,就是徹底使用沙箱機制,相互之間沒有任何接口,而且性能開銷極低。html

回憶一下,咱們傳統的Web應用部署方式通常都是將Web應用手動上傳到服務器,並手動安裝相關依賴和環境,再高級一點的咱們能夠用jenkins來自動化部署咱們的應用,包括自動化測試等等,雖然已經解決了咱們大部分部署的繁瑣問題,可是若是咱們服務器變動,或者遇到須要部署到多臺服務器的場景,那麼傳統的操做將會繁瑣。你們也許會問這種狀況會出現嗎?答案是會的。作過B端系統或有Saas系統開發經驗的朋友也許會清楚其中的繁瑣,爲了客戶安全和私有化每每須要研發人員給企業配置和部署獨立的Web應用,若是你有上百家客戶上千家客戶,咱們一個個部署顯然是效率極低的,並且不能保證環境的一致性和穩定性,由於一旦咱們的Web系統使用的環境或者包更新了,應用極可能不能正常Work,這種狀況下采用Docker容器化技術能夠很好的解決這一問題。前端

再者,前幾年比較火的雲計算服務,最爲直接的要求就是標準化快速交付,而Docker技術就很是適合這樣的要求。vue

目前大部分企業都在採用Docker來實現軟件開發部署中的自動化和部署效率安全等問題,做爲前端工程師,也須要掌握必定的Docker技術來更好的配合後端和運維來推動這一過程。java

你將收穫

  • Docker的基本應用場景和實現架構
  • Docker的基本用法
  • 使用Docker部署一個Web應用

正文

在開始正文以前首先咱們先來了解一下Docker的應用場景,這樣才能更好的理解爲何要使用它。 node

Docker 容許咱們使用本身提供的應用程序或服務的本地容器在標準化環境中工做,這將大大簡化咱們開發的生命週期。咱們還能夠用Docker配合Jenkins實現更加完整高效的自動化部署方案。

Docker 的三個基本概念以下:linux

  • 鏡像(Image):Docker 鏡像(Image),至關因而一個完整的root文件系統;
  • 容器(Container):鏡像和容器的關係,就像是面向對象程序設計中的類和實例同樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器能夠被建立、啓動、中止、刪除、暫停等;
  • 倉庫(Repository):可當作是一個代碼控制中心,用來保存鏡像。

其採用客戶端-服務器 (C/S) 架構模式,使用遠程API來管理和建立Docker容器。 Docker 容器經過 Docker鏡像來建立。容器與鏡像的關係相似於面向對象編程中的對象與類。爲了方便你們理解,筆者特地畫了一張Docker的架構圖,以下: webpack

Docker 基礎

1.1主機虛擬化(vm)與操做系統虛擬化(container)

主機虛擬化
操做系統虛擬化

由上圖對比可得,兩種虛擬化技術本質的區別是:主機虛擬化須要在父操做系統上運行一套子操做系統;而操做系統虛擬化是以進程的方式管理子容器,子容器與宿主機共用一套操做系統css3

主機虛擬化 操做系統虛擬化
隔離性 環境強隔離,父子操做系統底層無關 只能運行類似的操做系統,使用相似的庫
網絡 網絡傳輸效率低,啓動慢 傳輸效率高,啓動較快,響應快
佔用 必須增長操做系統的大量佔用 佔用較少
安全 子系統與宿主系統無關 有風險,但在可控範圍 (daemon)

1.2 容器化涉及內核技術

  • namespace —— 名稱空間是提供給每一個容器資源隔離的基礎,提供瞭如下屬性的隔離
    • UTS:每個NameSpace都擁有獨立的主機或域名,能夠把每一個NameSpace認爲一個獨立主機。
    • IPC:每一個容器依舊使用linux內核中進程交互的方法,實現進程間通訊
    • Mount:每一個容器的文件系統是獨立的Net:每一個容器的網絡是隔離
    • User:每一個容器的用戶和組ID是隔離,每一個容器都擁有root用戶
    • PID:每一個容器都擁有獨立的進程樹,由容器是物理機中的一個進程,因此容器中的進程是物理機的線程
  • control group ——控制組提供了對容器的資源限制
    • blkio -- 這個子系統爲塊設備設定輸入/輸出限制,好比磁盤,固態硬盤,USB 等等。
    • cpu -- 這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問。
    • cpuacct -- 這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。
    • cpuset -- 這個子系統爲 cgroup 中的任務分配獨立 CPU和內存節點。
    • devices -- 這個子系統可容許或者拒絕 cgroup 中的任務訪問設備。
    • freezer -- 這個子系統掛起或者恢復 cgroup 中的任務。
    • memory -- 這個子系統設定 cgroup 中任務使用的內存限制,並自動生成由那些任務使用的內存資源報告。
    • net_cls -- 這個子系統使用等級識別符(classid)標記網絡數據包,可容許 Linux 流量控制程序(tc)識別從具體 cgroup 中生成的數據包。
    • ns -- 名稱空間子系統

運行第一個docker 程序

2.1 安裝docker

參照docker官網安裝文檔強烈建議不使用windows 操做(本人沒有試過在windows上開發docker 相關,雖然官網提供了,但不知道),建議使用osx或linux)考慮服務器上國內使用centos 7 爲大部分介紹下centos 7的安裝(使用非root 帳號,自行加上sudo)

# 1.清除舊版本的docker 安裝
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
# 2.安裝依賴 官網介紹 yum-utils 爲了引入yum-config-manager 其餘的是docker 自身依賴
yum install -y yum-utils \
  										device-mapper-persistent-data \
  										lvm2
# 3.添加yum源 
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
# 4.列出對應的安裝版本
 yum list docker-ce --showduplicates | sort -r
# 5.安裝 建議根據實際狀況選擇版本 不要追求最新
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
# 6。設置開機啓動docker,並啓動docker 
systemctl enable docker && systemctl start docker
複製代碼

2.2 運行第一個docker 程序

# 查看docker 服務狀態
systemctl docker status
# 運行 第一個應用,前端接觸最多的容器就是nginx 了 
# 查詢官方 nginx stable 版本是1.16.1 因而選用 stable-alpine 版本
docker run -p 80:80 nginx:stable-alpine
複製代碼

3.docker 基本使用

3.1 docker命令介紹

docker全部命令可閱讀使用docker 命令行並可經過docker --help 查詢用法

docker --help

Usage:	docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/Users/mac/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/Users/mac/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/Users/mac/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/Users/mac/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes
複製代碼

3.2 docker 鏡像

3.2.1 常見用法

官方給的關於鏡像的描述是:"An image is a read-only template with instructions for creating a Docker container",含義是說 鏡像是一個只讀的用於指導建立容器的模板,至關於面向對象裏的類的含義 而容器即是對應的實例,經常使用的命令以下

# 下載鏡像
+ docker pull ubuntu

Using default tag: latest
latest: Pulling from library/ubuntu
423ae2b273f4: Pull complete
de83a2304fa1: Pull complete
f9a83bce3af0: Pull complete
b6b53be908de: Pull complete
Digest: sha256:04d48df82c938587820d7b6006f5071dbbffceb7ca01d2814f81857c631d44df
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
# 查看鏡像列表
+ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              72300a873c2c        2 weeks ago         64.2MB
# 導出鏡像爲文件,方便在不聯網的機器上使用docker image
+ docker save  ubuntu -o ubuntu.tar
# 刪除鏡像,可見它的操做是先清除tag 若是沒有其餘相同image佔用再清理layer
+ docker rmi ubuntu
Untagged: ubuntu:latest
Deleted: sha256:72300a873c2ca11c70d0c8642177ce76ff69ae04d61a5813ef58d40ff66e3e7c
Deleted: sha256:d3991ad41f89923dac46b632e2b9869067e94fcdffa3ef56cd2d35b26dd9bce7
Deleted: sha256:2e533c5c9cc8936671e2012d79fc6ec6a3c8ed432aa81164289056c71ed5f539
Deleted: sha256:282c79e973cf51d330b99d2a90e6d25863388f66b1433ae5163ded929ea7e64b
Deleted: sha256:cc4590d6a7187ce8879dd8ea931ffaa18bc52a1c1df702c9d538b2f0c927709d
# 從文件導入鏡像,方便在不聯網的機器上使用docker image
+ docker load -i ubuntu.tar

cc4590d6a718: Loading layer [=====================>]  65.58MB/65.58MB
8c98131d2d1d: Loading layer [=====================>]  991.2kB/991.2kB
03c9b9f537a4: Loading layer [=====================>]  15.87kB/15.87kB
1852b2300972: Loading layer [=====================>]  3.072kB/3.072kB
Loaded image: ubuntu:latest
# 構建鏡像, 可自定義構建本身的鏡像 下一部份詳細講
docker build -t $image:$tag $DockerfilePath
# 給鏡像打一個新標籤,通常用於推送到其餘倉庫
docker tag ubuntu $image:$tag
# 將鏡像推送到遠程registry
docker push $image:$tag

複製代碼
3.2.2 自定義構建鏡像

copy-on-write: docker 鏡像是以層爲結構的,底層通常爲基礎的操做系統,當文件系統發生變化時,首先從只讀層複製一個文件到讀寫層操做當該層讀寫完畢並提交後即在原來基礎上累加一層,當一個鏡像構建時會緩存全部成功的層提高構建速度.

嘗試經過物理安裝的方式講述一下本身構建nginx,咱們在物理機上安裝nginx 的步驟(源碼安裝能最大化保證穩定性和用到新的feature)可歸納爲如下幾步

# 1. 下載源碼包及依賴
yum install pcre-devel zlib-devel openssl-devel gcc make 
wget http://nginx.org/download/nginx-1.16.1.tar.gz	/usr/local/source/
# 2. 設置編譯nginx 的模塊
./configure \
        --prefix=/usr/local/nginx \
        --conf-path=/usr/local/nginx/nginx.conf \
        --pid-path=/usr/local/nginx/nginx.pid \
        --with-http_ssl_module \
        --with-pcre \
        --with-http_gzip_static_module
# 3. 編譯 & 安裝
make && make install
# 4. 啓動nginx
./nginx
複製代碼

實際在Dockerfile下也是這麼完成的。

1.編輯文件命名Dockerfile

FROM centos:centos7.2.1511
MAINTAINER xujiang@test.com
ADD http://nginx.org/download/nginx-1.16.1.tar.gz /usr/local/source/ RUN ["bash","-c","cd /usr/local/source && \ tar -xf nginx-1.16.1.tar.gz --strip-components 1 && \ yum update -y > /dev/null 2>&1 && \ yum install -y -q pcre-devel zlib-devel openssl-devel gcc make && \ ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-pcre --with- http_gzip_static_module && \ make && make install && \ ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx && \ rm -rf /usr/local/source"] CMD ["nginx", "-g", "daemon off;"] 複製代碼

2.在當前目錄下運行構建,即可構建成功 .表示當前目錄下構建

+ docker build -t mynginx:20200311 .
Step 1/4 : FROM centos:centos7.2.1511
 ---> 9aec5c5fe4ba
Step 2/4 : ADD http://nginx.org/download/nginx-1.16.1.tar.gz /usr/local/source/
Downloading [======================================>]  1.033MB/1.033MB
 ---> ac3b840c5563
Step 3/4 : RUN ["bash","-c","cd /usr/local/source && tar -xf nginx-1.16.1.tar.gz --strip-components 1 && yum update -y > /dev/null 2>&1 && yum install -y -q pcre-devel zlib-devel openssl-devel gcc make && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-pcre --with-http_gzip_static_module && make && make install && ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx && rm -rf /usr/local/source"]
 ---> 22efc447e0c2
Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
 ---> 8f74bded71e9
Successfully built 8f74bded71e9
Successfully tagged mynginx:20200311
複製代碼

3.運行該鏡像並暴露內部80端口指向外部8000:docker run -d -p 8000:80 --name mynginx-container mynginx:20200311

注:實際上nginx 構建全部內容遠遠比這個複雜,這裏可貼上nginx 構建的Dockerfile

​ 更多指令可參考Dockerfile Reference

3.3 docker 容器

上文提到容器是鏡像的運行時實例,一個鏡像能夠經過不一樣的命令運行不同的容器實例,如下是對容器的基本操做的經常使用命令

+ docker run --help
Usage:	docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
# -d 將容器運行在後臺並打印容器ID
-d, --detach  					Run container in background and print container ID
-e, --env list          Set environment variables
--env-file list         Read in a file of environment variables
--rm                    Automatically remove the container when it exits
-v, --volume list       Bind mount a volume
-w, --workdir string    Working directory inside the container
--restart string        Restart policy to apply when a container exits (default "no")
複製代碼
# 查看當前正在運行的容器 docker ps -a 表示查看全部容器(包含已經退出)
+ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
a5f7f9710db8        mynginx:20200311    "nginx -g 'daemon of…"   59 seconds ago      Up 58 seconds       0.0.0.0:80->80/tcp   mynginx-container
# 進入容器內部執行命令(打開標準輸入流併爲容器建立僞終端)
docker exec -it  mynginx-container bash
# 查看容器日誌
docker logs -f  mynginx-container
複製代碼

4.實戰案例

1.準備

* 一個前端項目
* 一臺安裝好docker 的機器
* [docker hub](https://hub.docker.com/)查詢編譯所須要的鏡像[node](https://hub.docker.com/_/node?tab=tags),[nginx](https://hub.docker.com/_/nginx)
複製代碼
# 克隆antd-admin.git 項目
git clone https://github.com/zuiidea/antd-admin.git
# 使用docker 編譯的優點 能夠在任意一臺只裝了docker的環境下編譯不一樣的語言 消除對環境依賴
docker run --network=host --rm  -v "$(cd $(dirname .);pwd):/app" -w /app node:10-alpine3.9 yarn && yarn build
複製代碼
  • 準備反向代理的規則的nginx.conf
server {
    listen       80;
    server_name  _;
    access_log  /var/log/nginx/host.access.log  main;

    location / {
        add_header Access-Control-Allow-Origin *;
    	  add_header Access-Control-Allow-Headers X-Requested-With;
	      add_header Access-Control-Allow-Methods GET,POST;
        root   /app;
        index  index.html index.htm;
    }
}
複製代碼
  • 構建本身的Dockerfile 並寫成腳本
FROM nginx:stable-alpine
ENV LANG en_US.UTF-8
COPY dist /app COPY app.conf /etc/nginx/conf.d/default.conf WORKDIR /app 複製代碼
  • 參考腳本以下 build.sh
#!/bin/bash 
current_dir=$(cd $(dirname .);pwd)

function compire(){
 docker run --network=host --rm  -v "$current_dir:/app" -w /app node:10-alpine3.9 yarn && yarn build
}
function package(){
 if [ ! -d "$current_dir/dist" ] ;then
  compire
 fi
 docker build -t myapp:`date -u +"%Y%m%d"` $current_dir
}
function clean(){
 rm -rf $current_dir/dist
}

case "$1" in
  compire)
   compire
  ;;
  package)
   package
  ;;
  clean)
  clean
  ;;
  *)
  echo "USAGE:$0 package | compire | clean "
esac
複製代碼
  • 運行容器docker run -d -p 80:80 myapp:20200311

至此,基本的配置就完成了,你們能夠本身手動試試,基於Docker部署一個本身的Web應用。

本文只涉及到了Docker基本的使用配置,後期筆者有空會繼續和朋友總結編排docker networkdocker volumedocker daemon等技術,並以一個node的案例部署做爲實戰來教你們在實際項目中去落地Docker自動化部署。

若是想獲取更多項目完整的源碼, 或者想學習更多H5遊戲, webpacknodegulpcss3javascriptnodeJScanvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。

更多推薦

相關文章
相關標籤/搜索