[TOC]
## 為什么docker會采取這種分層結構?
資源共享。采用分層機制實現基礎層共享,從而減小docker倉庫整體體積
基礎:https://blog.csdn.net/m0_46090675/article/details/121597421
docker鏡像的實質是由一層層文件系統組成
boots (boot file system)主要包含bootloader和kernel, bootloader主要是引導加載kernel, Linux剛啟動時會加載boots文件系統。在docke鏡像的最底層就是bootfs。這一層與Linux(Univx系統是一樣的,包含boot加載器(bootoader)和內核(kermnel)。當boot加載完,后整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時會卸載bootfs。
rootfs (root file system),在bootfs之上,包含的就是典型的linux系統中的/dev/proc,/bin,/etc等標準的目錄和文件。rootfs就是各種不同的操作系統發行版,比如Ubuntu/Centos等等。
我們平時安裝進虛擬機的centos都有1到幾個GB,為什么docer這里才20OMB?對于一個精簡的OS,roots可以很小,只需要包括最基本的命令,工具,和程序庫就可以了,因為底層直接使用Host的Kernal,自己只需要提供rootfs就行了。由此可見不同的linux發行版,他們的bootfs是一致的,rootfs會有差別。因此不同的發行版可以共用bootfs。

## 生命周期

## docker鏡像啟動流程

## 基本命令
docker info 查看的是docker 服務的信息
### 鏡像
|命令 | 解釋 | eg|
| --- | --- |---|
| docker images | 列出屬于鏡像 | |
|docker images xxx | 鏡像名字,根據名稱列出鏡像 ||
| docker images -q| 只列出鏡像的id ||
| docker search xxx |查找鏡像 ||
|docker rmi xxx | 刪除鏡像||
|docker image inspect xxx | 查看鏡像信息||
|docker pull xxx | 下載鏡像||
|docker push xxx | 推送鏡像||
|docker image save xxx > /path/xxx.tgz| 導出某鏡像| docker images save nginx|
|docker image load -i /path/xxx.tgz | 導出某鏡像| docker images load -i /docker-test/nginx.tgz|
|docker cp 容器id:容器內路徑 目的主機路徑 | 拷貝容器的文件到主機中| |
|docker cp 目的主機路徑 容器id:容器內路徑 | 拷貝宿主機的文件到容器中| |
### 容器
|命令 | 解釋 | eg|
| --- | --- |---|
|docker run xxx|創建+啟動,本地存在就直接啟動,沒有就先下載再啟動 | |
|docker exec -it 容器id或者容器名 bash(命令行) | 交互式進入運行的容器||
|docker ps | 查看運行的容器||
|docker ps -a | 查看所有容器||
|docker stop xxx | 停止容器||
|docker container kill xxx |停止容器 ||
|docker rm xxx | 刪除容器 ||
|docker rm -f `docker ps -aq |刪除所有容器 ||
|docker run -d -p port(宿主機port):port(容器port) xxx| 運行容器,并映射端口||
|docker logs xxx| 查看日志||
|docker container inspect xxx | 查看鏡像信息||
|docker port 容器id | 查看容器端口||
|docker commit xxx | 提交容器||
|docker export xxx > xxx.tar|導出容器| docker export nginx >nginx.tar|
|docker import xxx nnn | 導入 容器|docker import cnetos-8-vim.tgz cent-vin(鏡像的名字) |
>隨機端口 -P
>docker commit 容器的id docker賬號/鏡像名字
>docker run xxx 只會啟動容器,并停止,只能通過docker ps -a查看,因為沒有前臺運行命令
eg:docker run nginx , 是錯誤的,只能 docker run -it -d nginx bash
>docker run -d -rm xxx 停止就刪除
-- name xxx(名字)
### 其他命令
| 命令 | 解釋 |
| --- | --- |
|docker logs -f 容器id | 跟蹤容器日志 |
|docker logs -ft 容器id | 跟蹤容器日志和時間戳 |
|docker top 容器id | 查看容器進程 |
|docker stats | 查看容器列表系統資源狀態 |
## 數據卷
卷就是目錄或文件,存在于一個或多個容器中,由Docker掛載到容器,但卷不屬于聯合文件系統(Union FileSystem),因此能夠繞過聯合文件系統提供一些用于持續存儲或共享數據的特性。
數據卷的特性:
* 數據卷可以在容器之間或容器與宿主機之間共享和重用
* 對數據卷的修改會立馬生效
* 對數據卷的更新,不會影響鏡像
* 數據卷會一直存在,即使容器被刪除
>自定義數據卷目錄
~~~
docker run -it -v 主機目錄(絕對路徑):容器目錄
例如
docker run --name tomcat02 -d -p 8082:8080 -v /soft/wabapps:/usr/local/tomcat/webapps tomcat:latest
~~~
>自動數據卷目錄
~~~
docker run --name tomcat03 -d -p 8082:8080 -v aaa:/usr/local/tomcat/webapps tomcat:latest
注意:
1.aa代表一個數據卷名字,名稱可以隨便寫, docker在不存在時自動創建這個數據卷同時自動映射宿主機中某個目錄
2.同時在啟動容器時會將aa對應容器目錄中全部內容復制到aa映射目錄中
~~~
> 列出所有數據卷
docker volume ls
> 查看具體的數據卷信息
docker volume inspect 卷名
>創建數據卷
docker volume create bb
啟動容器時候,可以直接 -v bb:/var/lib/tomcat/webapps
>刪除
docker volume rm bb
## Docker 網絡
https://blog.csdn.net/lihongbao80/article/details/108019773
> 查看默認網絡:docker network ls
### 自定義網橋
~~~
docker network create -d bridge --subnet 192.168.1.2/24 my_network
然后運行:docker run -d -p 80:8080 --name tomcat01 --network my_network
其中 --subnet 可以不指定
~~~
>查看網橋信息及網橋下活躍的容器 docker network inspect bridge
>刪除網橋:docker network rm 網橋名稱
刪除未使用的網絡:docker network prune #ps: -f 強制刪除,不提供任何確認情況下刪除.
將一個容器加入到一個網絡中:docker network connect 網絡名稱 容器ID
從網絡中斷開一個容器的鏈接:docker network disconnect 網絡名稱 容器 ID # ps: -f 強制刪除,不提供任何確認情況下刪除.
注意:
一旦在啟動容器時指定了自建網橋之后,日后可以在任何這個網橋關聯的容器中使用容器名字進行與其他容器通信(將容器名字解析到容器DNS中)
### 創建網絡
~~~
docker network create (appnet)名稱 --subnet 10.224.0.0/16(網段)
~~~
啟動容器,加入自己的網絡
eg:
```
docker run --name alpine2 --rm --net appnet alpine:3.15 ifconfig
```
## docker網絡模式
### bridge模式,--net=bridge(默認)
這是dokcer網絡的默認設置,為容器創建獨立的網絡命名空間,容器具有獨立的網卡等所有單獨的網絡棧,是最常用的使用方式。在docker run啟動容器的時候,如果不加–net參數,就默認采用這種網絡模式。安裝完docker,系統會自動添加一個供docker使用的網橋docker0,我們創建一個新的容器時,容器通過DHCP獲取一個與docker0同網段的IP地址,并默認連接到docker0網橋,以此實現容器與宿主機的網絡互通。
### host模式,--net=host
Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等。一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、Iptable規則等都與其他的Network Namespace隔離。一個Docker容器一般會分配一個獨立的Network Namespace。但如果啟動容器的時候使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。。
### none模式,--net=none
為容器創建獨立網絡命名空間,但不為它做任何網絡配置,容器中只有lo,用戶可以在此基礎上,對容器網絡做任意定制。這個模式下,dokcer不為容器進行任何網絡配置。需要我們自己為容器添加網卡,配置IP。因此,若想使用pipework配置docker容器的ip地址,必須要在none模式下才可以。
### 其他容器模式(即container模式,join模式),--net=container:NAME_or_ID
與host模式類似,只是容器將與指定的容器共享網絡命名空間。這個模式就是指定一個已有的容器,共享該容器的IP和端口。除了網絡方面兩個容器共享,其他的如文件系統,進程等還是隔離開的。
### 用戶自定義
docker 1.9版本以后新增的特性,允許容器使用第三方的網絡實現或者創建單獨的bridge網絡,提供網絡隔離能力。
> 這些網絡模式在相互網絡通信方面的對比如下所示

南北向通信指容器與宿主機外界的訪問機制,東西向流量指同一宿主機上,與其他容器相互訪問的機制。
**`1)host模式`**
由于容器和宿主機共享同一個網絡命名空間,換言之,容器的IP地址即為宿主機的IP地址。所以容器可以和宿主機一樣,使用宿主機的任意網卡,實現和外界的通信。網絡模型可以參照下圖

采用host模式的容器,可以直接使用宿主機的IP地址與外界進行通信,若宿主機具有公有IP,那么容器也擁有這個公有IP。同時容器內服務的端口也可以使用宿主機的端口,無需額外進行NAT轉換,而且由于容器通信時,不再需要通過linuxbridge等方式轉發或數據包的拆封,性能上有很大優勢。當然,這種模式有優勢,也就有劣勢,主要包括以下幾個方面:
1)最明顯的就是容器不再擁有隔離、獨立的網絡棧。容器會與宿主機競爭網絡棧的使用,并且容器的崩潰就可能導致宿主機崩潰,在生產環境中,這種問題可能是不被允許的。
2)容器內部將不再擁有所有的端口資源,因為一些端口已經被宿主機服務、bridge模式的容器端口綁定等其他服務占用掉了。
**`2)bridge模式`**
bridge模式是docker默認的。在這種模式下,docker為容器創建獨立的網絡棧,保證容器內的進程使用獨立的網絡環境,實現容器之間、容器與宿主機之間的網絡棧隔離。同時,通過宿主機上的docker0網橋,容器可以與宿主機乃至外界進行網絡通信。其網絡模型可以參考下圖:

從上面的網絡模型可以看出,容器從原理上是可以與宿主機乃至外界的其他機器通信的。同一宿主機上,容器之間都是連接掉docker0這個網橋上的,它可以作為虛擬交換機使容器可以相互通信。然而,由于宿主機的IP地址與容器veth pair的 IP地址均不在同一個網段,故僅僅依靠veth pair和namespace的技術,還不足以使宿主機以外的網絡主動發現容器的存在。為了使外界可以方位容器中的進程,docker采用了端口綁定的方式,也就是通過iptables的NAT,將宿主機上的端口端口流量轉發到容器內的端口上。舉一個簡單的例子,使用下面的命令創建容器,并將宿主機的3306端口綁定到容器的3306端口:
```
docker run -tid --name db -p 3306:3306 MySQL
```
在宿主機上,可以通過iptables -t nat -L -n,查到一條DNAT規則:
```
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306
```
上面的172.17.0.5即為bridge模式下,創建的容器IP。
很明顯,bridge模式的容器與外界通信時,必定會占用宿主機上的端口,從而與宿主機競爭端口資源,對宿主機端口的管理會是一個比較大的問題。同時,由于容器與外界通信是基于三層上iptables NAT,性能和效率上的損耗是可以預見的。
**`3)none模式`**
在這種模式下,容器有獨立的網絡棧,但不包含任何網絡配置,只具有lo這個loopback網卡用于進程通信。也就是說,none模式為容器做了最少的網絡設置,但是俗話說得好“少即是多”,在沒有網絡配置的情況下,通過第三方工具或者手工的方式,開發這任意定制容器的網絡,提供了最高的靈活性
**`4)其他容器(container)模式`**
其他網絡模式是docker中一種較為特別的網絡的模式。在這個模式下的容器,會使用其他容器的網絡命名空間,其網絡隔離性會處于bridge橋接模式與host模式之間。當容器共享其他容器的網絡命名空間,則在這兩個容器之間不存在網絡隔離,而她們又與宿主機以及除此之外其他的容器存在網絡隔離。其網絡模型可以參考下圖:

在這種模式下的容器可以通過localhost來同一網絡命名空間下的其他容器,傳輸效率較高。而且這種模式還節約了一定數量的網絡資源,但它并沒有改變容器與外界通信的方式。在一些特殊的場景中非常有用,例如,kubernetes的pod,kubernetes為pod創建一個基礎設施容器,同一pod下的其他容器都以其他容器模式共享這個基礎設施容器的網絡命名空間,相互之間以localhost訪問,構成一個統一的整體。
**`5)用戶定義網絡模式`**
在用戶定義網絡模式下,開發者可以使用任何docker支持的第三方網絡driver來定制容器的網絡。并且,docker 1.9以上的版本默認自帶了bridge和overlay兩種類型的自定義網絡driver。可以用于集成calico、weave、openvswitch等第三方廠商的網絡實現。 除了docker自帶的bridge driver,其他的幾種driver都可以實現容器的跨主機通信。而基于bdrige driver的網絡,docker會自動為其創建iptables規則,保證與其他網絡之間、與docker0之間的網絡隔離。 例如,使用下面的命令創建一個基于bridge driver的自定義網絡:
```
docker network create bri1
```
則docker會自動生成如下的iptables規則,保證不同網絡上的容器無法互相通信。
```
A DOCKER-ISOLATION -i br-8dba6df70456 -o docker0 -j DROP
A DOCKER-ISOLATION -i docker0 -o br-8dba6df70456 -j DROP
```
除此之外,bridge driver的所有行為都和默認的bridge模式完全一致。而overlay及其他driver,則可以實現容器的跨主機通信。
- Go準備工作
- 依賴管理
- Go基礎
- 1、變量和常量
- 2、基本數據類型
- 3、運算符
- 4、流程控制
- 5、數組
- 數組聲明和初始化
- 遍歷
- 數組是值類型
- 6、切片
- 定義
- slice其他內容
- 7、map
- 8、函數
- 函數基礎
- 函數進階
- 9、指針
- 10、結構體
- 類型別名和自定義類型
- 結構體
- 11、接口
- 12、反射
- 13、并發
- 14、網絡編程
- 15、單元測試
- Go常用庫/包
- Context
- time
- strings/strconv
- file
- http
- Go常用第三方包
- Go優化
- Go問題排查
- Go框架
- 基礎知識點的思考
- 面試題
- 八股文
- 操作系統
- 整理一份資料
- interface
- array
- slice
- map
- MUTEX
- RWMUTEX
- Channel
- waitGroup
- context
- reflect
- gc
- GMP和CSP
- Select
- Docker
- 基本命令
- dockerfile
- docker-compose
- rpc和grpc
- consul和etcd
- ETCD
- consul
- gin
- 一些小點
- 樹
- K8s
- ES
- pprof
- mycat
- nginx
- 整理后的面試題
- 基礎
- Map
- Chan
- GC
- GMP
- 并發
- 內存
- 算法
- docker