寫給前端工程師的 docker 快速入門教程

前幾天寫了一篇文章 前端部署發展史[1],前端部署的發展離不開 devops 的發展,而 devops 又得益於 docker 的發展。因此,前端掌握 docker 也勢在必行,何況它又不是很難

docker 使應用部署更加輕量,可移植,可擴展。更好的環境隔離也更大程度地避免了生產環境與測試環境不一致的巨大尷尬。由於 docker 輕便可移植的特點也極大促進了 CI/CD 的發展。

術語

docker 的架構圖如下

docker architecture

從圖中可以看出幾個組成部分

  • docker client: 即 docker 命令行工具

  • docker host: 宿主機,docker daemon 的運行環境服務器

  • docker daemon: docker 的守護進程,docker client 通過命令行與 docker daemon 交互

  • container: 最小型的一個操作系統環境,可以對各種服務以及應用容器化

  • image: 鏡像,可以理解爲一個容器的模板配置,通過一個鏡像可以啓動多個容器

  • registry: 鏡像倉庫,存儲大量鏡像,可以從鏡像倉庫拉取和推送鏡像

安裝 docker

參考在 centos 上安裝 docker 的官方文檔: https://docs.docker.com/install/linux/docker-ce/centos/

以下是在 centos 上安裝 docker 的命令示例過程

安裝依賴

$ yum install -y yum-utils device-mapper-persistent-data lvm2

添加 docker 的 yum 鏡像源,如果在國內,添加阿里雲的鏡像源

# 安裝 docker 官方的鏡像源
$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 如果在國內,安裝阿里雲的鏡像
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安裝指定版本的 docker 並且啓動服務

# 安裝 docker
$ yum install -y docker-ce

# 安裝指定版本號的 docker,以下是 k8s 官方推薦的 docker 版本號 (此時,k8s 的版本號在 v1.16)
$ yum install -y docker-ce-18.06.2.ce

$ systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

$ systemctl start docker

docker 安裝成功後,可以使用以下命令查看版本號

$ docker --version
Docker version 18.06.2-ce, build 6d37f41

#
查看更詳細的版本號信息
$ docker version

#
查看docker的詳細配置信息
$ docker info

守護進程配置

dockerddocker 的守護進程,dockerd 可以通過配置文件進行配置,在 linux 下的配置文件位置在 /etc/docker/daemon.json,更詳細內容可以參考 官方文檔[2]

日誌引擎爲 json-file,對日誌結構化,結合合適的日誌系統,方便定位日誌。存儲引擎爲 overrlay2

$ mkdir /etc/docker

# 設置 docker daemon
$ cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF

# 重啓 docker
$ systemctl daemon-reload
$ systemctl restart docker

底層原理

docker 底層使用了一些 linux 內核的特性,大概有 namespacecgroupsufs

namespace

docker 使用 linux namespace 構建隔離的環境,它由以下 namespace 組成

  • pid: 隔離進程

  • net: 隔離網絡

  • ipc: 隔離 IPC

  • mnt: 隔離文件系統掛載

  • uts: 隔離 hostname

  • user: 隔離 uid/gid

control groups

也叫 cgroups,限制資源配額,比如某個容器只能使用 100M 內存

Union file systems

UnionFS 是一種分層、輕量級並且高性能的文件系統,支持對文件系統的修改作爲一次提交來一層層的疊加。docker 的鏡像與容器就是分層存儲,可用的存儲引擎有 aufsoverlay 等。

關於分層存儲的詳細內容可以查看官方文檔 docker: About storage drivers[3]

鏡像

鏡像是一份用來創造容器的配置文件,而容器可以視作最小型的一個操作系統。

docker 的鏡像和容器都使用了 unionFS 做分層存儲,鏡像作爲只讀層是共享的,而容器在鏡像之上附加了一層可寫層,最大程度地減少了空間的浪費,詳見下圖

分層存儲

鏡像倉庫與拉取

大部分時候,我們不需要自己構建鏡像,我們可以在官方鏡像倉庫[4]拉取鏡像

可以簡單使用命令 docker pull 拉取鏡像。拉取鏡像後可以使用 docker inspect 查看鏡像信息

# 加入拉取一個 node:alpine 的鏡像
$ docker pull node:alpine

# 查看鏡像信息
$ docker inspect node:alpine

# 列出所有鏡像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node alpine f20a6d8b6721 13 days ago 105MB
mongo latest 965553e202a4 2 weeks ago 363MB
centos latest 9f38484d220f 8 months ago 202MB

構建鏡像與發佈

但並不是所有的鏡像都可以在鏡像倉庫中找到,另外我們也需要爲我們自己的業務應用去構建鏡像。

使用 docker build 構建鏡像,docker build 會使用當前目錄的 dockerfile 構建鏡像,至於 dockerfile 的配置,參考下節。

-t 指定標籤

# -t node-base:10: 鏡像以及版本號
# .: 指當前路徑
$ docker build -t node-base:10 .

當構建鏡像成功後可以使用 docker push 推送到鏡像倉庫

Dockerfile

在使用 docker 部署自己應用時,往往需要自己構建鏡像。docker 使用 Dockerfile 作爲配置文件構建鏡像,簡單看一個 node 應用構建的 dockerfile

FROM node:alpine

ADD package.json package-lock.json /code/
WORKDIR /code

RUN npm install --production

ADD . /code

CMD npm start

FROM

基於一箇舊有的鏡像,格式如下

FROM <image> [AS <name>]

# 在多階段構建時會用到
FROM <image>[:<tag>] [AS <name>]

ADD

把目錄,或者 url 地址文件加入到鏡像的文件系統中

ADD [--chown=<user>:<group>] <src>... <dest>

RUN

執行命令,由於 ufs,它會在當前鏡像的頂層新增一層

RUN <command>

CMD

指定容器如何啓動

一個 Dockerfile 中只允許有一個 CMD

# exec form, this is the preferred form
CMD ["executable","param1","param2"]

# as default parameters to ENTRYPOINT
CMD ["param1","param2"]

# shell form
CMD command param1 param2

容器

鏡像與容器的關係,類似於代碼與進程的關係。

  • docker run 創建容器

  • docker stop 停止容器

  • docker rm 刪除容器

創建容器

基於 nginx 鏡像創建一個最簡單的容器:啓動一個最簡單的 http 服務

使用 docker run 來啓動容器,docker ps 查看容器啓動狀態

$ docker run -d --name nginx -p 8888:80 nginx:alpine

$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
404e88f0d90c nginx:alpine "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 0.0.0.0:8888->80/tcp nginx
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

其中:

  • -d: 啓動一個 daemon 進程

  • --name: 爲容器指定名稱

  • -p host-port:container-port: 宿主機與容器端口映射,方便容器對外提供服務

  • nginx:alpine: 基於該鏡像創建容器

此時在宿主機使用 curl 測試容器提供的服務是否正常

$ curl localhost:8888
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

那如果要進入容器環境中呢?使用 docker exec -it container-name sh 命令

$ docker exec -it nginx sh
/ #
/ #
/ #

容器管理

docker ps 列出所有容器

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
404e88f0d90c nginx:alpine "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 0.0.0.0:8888->80/tcp nginx
498e7d74fb4f nginx:alpine "nginx -g 'daemon of…" 7 minutes ago Up 7 minutes 80/tcp lucid_mirzakhani
2ce10556dc8f redis:4.0.6-alpine "docker-entrypoint.s…" 2 months ago Up 2 months 0.0.0.0:6379->6379/tcp apolloserverstarter_redis_1

docker port 查看容器端口映射

$ docker port nginx
80/tcp -> 0.0.0.0:8888

docker stats 查看容器資源佔用

$ docker stats nginx
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
404e88f0d90c nginx 0.00% 1.395MiB / 1.796GiB 0.08% 632B / 1.27kB 0B / 0B 2

參考資料

[1]

前端部署發展史: https://juejin.im/post/5dc4ae67f265da4cfa7bbb9a

[2]

官方文檔: https://docs.docker.com/engine/reference/commandline/dockerd/

[3]

docker: About storage drivers: https://docs.docker.com/storage/storagedriver/

[4]

官方鏡像倉庫: https://hub.docker.com/explore/

❤️ 看完三件事

如果你覺得這篇內容對你挺有啓發,我想邀請你幫我三個小忙:

  1. 點個「在看」,讓更多的人也能看到這篇內容(喜歡不點在看,都是耍流氓 -_-)

  2. 關注我的博客 https://github.com/SHERlocked93/blog,讓我們成爲長期關係

  3. 關注公衆號「前端下午茶」,持續爲你推送精選好文,也可以加我爲好友,隨時聊騷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章