## docker
**author: 收集整理自互聯網**
**last update: 2022-12-15 22:23:11**
----
[TOC=3,8]
----
### 什么是云原生?
[Pivotal](https://baijiahao.baidu.com/s?id=1642528154354438867) 公司的 Matt Stine 于2013年首次提出云原生(CloudNative)的概念;2015年,云原生剛推廣時,Matt Stine 在《遷移到云原生架構》一書中定義了符合云原生架構的幾個特征:12因素、微服務、自敏捷架構、基于 API 協作、扛脆弱性;到了2017年,Matt Stine 在接受 InfoQ 采訪時又改了口風,將云原生架構歸納為模塊化、可觀察、可部署、可測試、可替換、可處理6特質;而 Pivotal 最新官網對云原生概括為4個要點:DevOps + 持續交付 + 微服務 + 容器。[什么是云原生?這回終于有人講明白了 - 知乎](https://zhuanlan.zhihu.com/p/150190166)
2004年,谷歌開始使用容器技術。到了2006年,谷歌發布了 Cgroups ,最初叫 Process Container(進程容器)。Process Container 發布后第二年就進入了 Linux 內核主干。為避免混亂,就更名為 Control Groups,也就是 Cgroups。
9年前,Netscape 公司的創始人馬克·安德森說:“軟件正在吞噬世界”。6年前,OpenStack 基金會創 Jonathan Bryce 補充說:“世界的一切源于開源”。再之后,業內普遍認同“云計算已改變了天空的顏色”。但近兩年云計算概念又被清晰細分,“云原生”才是那條最大的魚。“大魚”來了,我們能做的不是墨守成規,而是擁抱“大魚”。讓我們了解云原生,擁抱云原生,追隨云原生。[到底什么是“云原生”? - 墨天輪](https://www.modb.pro/db/335891)
[云原生新手入門指南 · Kubernetes 中文指南——云原生應用架構實戰手冊](https://jimmysong.io/kubernetes-handbook/cloud-native/quick-start.html)
----
### 初識 docker


#### docker 是什么?
docker 是容器化工具,是通往 云原生時代 的船票。
docker 以簡練易用的使用范式,極大地降低了容器技術的使用慢門檻,由此帶來了云原生技術革命,這個時代還有比它更牛逼的東西嗎?
信息技術革命:Unix > Linux > TCP/IP > Web > Docker
----
#### docker 不是什么?
1. docker 不是虛擬機,不提供 宿主機虛擬化功能
2. docker 不是操作系統,它不包含操作系統內核,只包含 root 文件系統
> 如果和虛擬機作類比,那么 **docker 是半虛擬化方案(或稱為輕量級虛擬化)**,而 Oracle VM VirtualBox 等產品則是全虛擬化方案。
----
#### 為什么是 docker?
人們總想要得更多(虛擬化、隔離),但不想付出太多(虛擬機成本),而 docker 剛好迎合了 “多·快·好·省” 的需求點。
----
#### 不用 docker 的三大理由
1. 我喜歡配一整天的環境啥事也不干,我非常享受配環境的這個過程。
2. 我追求真實,都是直接買服務器,不用虛擬的容器。
3. [云原生](https://landscape.cncf.io/)、DevOps 這些對我來說就是炒作和噱頭,不符合我樸實的價值觀。
4. 相較于 “一次發布、隨處運行” ,我更喜歡折騰和風浪。
----
#### docker 的好處與局限性
1. Docker 是基于 Linux 64bit 的,無法在 32bit 的 linux/Windows/unix 環境下使用
2. LXC 是基于 Cgroup 等 Linux kernel 功能的,因此 Container 的 Guest 系統只能是 Linux base 的
3. 網絡限制
> 容器網絡(Docker Network )讓你可以方便地在同一主機下對容器進行網絡連接。加上一些其他的工作,你就可以跨主機使用疊加網絡功能。然而,也就到此為止了。網絡配置操作是受限的,而且到目前為止可以說這些手段都是人工的。盡管容器腳本化可以規模化,因為你必須給網絡定義增加預分配實例,每次提供容器時還需要額外步驟,這容易引起錯誤。
4. cgroup 的 cpu 和 cpuset 提供的 cpu 功能,相比 KVM 的等虛擬化方案相比難以度量(所以 dotcloud 主要是按內存收費)
5. docker 對 disk 的管理比較有限
6. container 隨著用戶進程的停止而銷毀,container 中的 log 等用戶數據不便收集
7. 庫控制受限
9. 沒有清晰的審計跟蹤
----
### 最簡單的,docker 可以幫我做什么?
安裝一個軟件環境很麻煩,如原生安裝一次 pulsar 環境,好不容易成功了,下次換一臺機器還要再重來一次,就算你用腳本將安裝過程自動化了,但還是不能保證百分百成功并和之前的配置一模一樣,這簡直是噩夢!
如果有一種方式讓我們只用成功安裝一次,后面在其他機器上安裝時能夠直接復制之前的成功成果就好了,這樣無論安裝過程多么復雜,多么艱辛,都沒有關系,只要我們成功一次,只要一次,就夠了!只要成功一次,就意味著后面的無數次再也沒有任何負擔了。
這就是 docker 能夠幫助我們做的事,我們將第一次的成功打包成一個鏡像,后面的千萬次只用重復運行這個鏡像就行了,只用簡單的重復就行了,保證和第一個毫無二致,運行鏡像的過程就像啟動一個進程那么簡單快速,沒有安裝、構建過程,沒有等待,一鍵部署,開箱即用,一次打包,到處運行,這就是 docker 帶給我們的魔法。
----
### docker 使用
#### docker 中的概念
##### 鏡像
操作系統分為 **內核** 和 **用戶空間**。內核啟動后,會掛載 root 文件系統(`/` 根文件系統)為其提供用戶空間支持。而 Docker 鏡像(Image),就相當于是一個 root 文件系統,比如官方鏡像 `ubuntu:18.04` 就包含了完整的一套 Ubuntu 18.04 最小系統的`root`文件系統。
鏡像除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。**鏡像不包含任何動態數據,其內容在構建之后也不會被改變**。
鏡像是容器的基礎,每次執行 `docker run` 的時候都會**指定以哪個鏡像作為容器運行的基礎。**
[Docker 鏡像 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/basic_concept/image/)
鏡像就是構建物,就是 環境 + 可執行程序,一次構建,多處立即運行。
~~~
$: docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 15 months ago 13.3kB
~~~
~~~
鏡像id
標簽1
標簽2
...
~~~
[分層存儲](https://vuepress.mirror.docker-practice.com/basic_concept/image/#分層存儲)
鏡像加速:
```shell
$ vi /etc/docker/daemon.json
{
"registry-mirrors": [
"https://h5m24cso.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
$: sudo systemctl daemon-reload
$: sudo systemctl restart docker
```
##### 構建緩存
[Dockerfile 最佳實踐 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/appendix/best_practices/#構建緩存)
~~~
對于 ADD 和 COPY 指令,鏡像中對應文件的內容也會被檢查,每個文件都會計算出一個校驗和。文件的最后修改時間和最后訪問時間不會納入校驗。在緩存的查找過程中,會將這些校驗和和已存在鏡像中的文件校驗和進行對比。如果文件有任何改變,比如內容和元數據,則緩存失效。
除了 ADD 和 COPY 指令,緩存匹配過程不會查看臨時容器中的文件來決定緩存是否匹配。例如,當執行完 RUN apt-get -y update 指令后,容器中一些文件被更新,但 Docker 不會檢查這些文件。這種情況下,只有指令字符串本身被用來匹配緩存。
一旦緩存失效,所有后續的 Dockerfile 指令都將產生新的鏡像,緩存不會被使用。
~~~
[https://vuepress.mirror.docker-practice.com/appendix/best_practices/#run](https://vuepress.mirror.docker-practice.com/appendix/best_practices/#run)
> 使用 `RUN apt-get update && apt-get install -y` 可以確保你的 `Dockerfiles` 每次安裝的都是包的最新的版本,而且這個過程不需要進一步的編碼或額外干預。這項技術叫作 `cache busting`。
[使用 BuildKit 構建鏡像 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/buildx/buildkit/#)
[Composer install in Dockerfile Without Breaking Cache | Sentinel Stand](https://www.sentinelstand.com/article/composer-install-in-dockerfile-without-breaking-cache)
> The COPY instruction will copy your application's source directory to the file system of the container. These files have likely been changed and the COPY instruction will invalidate the cache, which means that all subsequent Dockerfile instructions will run on every build.
> 這`COPY`指令會將應用程序的源目錄復制到容器的文件系統。 這些文件可能已被更改并且`COPY`指令將使緩存失效,這意味著所有后續的 Dockerfile 指令將在每個構建上運行。
----
##### 倉庫
鏡像構建完成后,可以很容易的在當前宿主機上運行,但是,如果需要在其它服務器上使用這個鏡像,我們就需要一個集中的存儲、分發鏡像的服務,[Docker Registry](https://hub.docker.com) 就是這樣的服務。
每個倉庫可以包含多個 標簽(Tag);每個標簽對應一個鏡像。
通常,一個倉庫會包含同一個軟件不同版本的鏡像,而**標簽就常用于對應該軟件的各個版本**。我們可以通過 `<倉庫名>:<標簽>` 的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標簽,將以 `latest` 作為默認標簽。
倉庫名經常以兩段式路徑形式出現,比如 `jwilder/nginx-proxy` ,前者往往意味著 Docker Registry 多用戶環境下的用戶名,后者則往往是對應的軟件名。但這并非絕對,取決于所使用的具體 Docker Registry 的軟件或服務。(**官方倉庫可以省略用戶名**)
以 [Ubuntu 鏡像](https://hub.docker.com/_/ubuntu) 為例,ubuntu 是倉庫的名字,其內包含有不同的版本標簽,如,`16.04`, `18.04`。我們可以通過 `ubuntu:16.04`,或者 `ubuntu:18.04` 來具體指定所需哪個版本的鏡像。如果忽略了標簽,比如 `ubuntu`,那將視為 `ubuntu:latest`。
https://hub.docker.com/_/ubuntu
https://hub.docker.com/layers/library/debian/bullseye-slim/images/sha256-76cdda8fe5eb597ef5e712e4c9a9f5f1fb119e69f353daaa7bd6d0f6e66e541d?context=explore
https://github.com/docker-library/php/blob/b9f17156020c3aef71df681b27684533529347a7/7.4/bullseye/cli/Dockerfile
https://hub.docker.com/layers/library/php/7.4-cli-bullseye/images/sha256-e6c15481f8b9999f4f099936c59dad3477a86d9affda1f5a023b1ed527764de0?context=explore
~~~
php:7.4-cli-bullseye 158.71 MB
debian:bullseye-slim 29.96 MB
~~~
[docker鏡像的版本(bullseye、buster、slim、alphine)_alun550的博客-CSDN博客_docker 鏡像版本](https://blog.csdn.net/alun550/article/details/123184731)
[鏡像加速器 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/install/mirror/#)
登錄到 docker 鏡像倉庫:
~~~
docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: xiaobu191
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
~~~
----
##### 容器
**鏡像是靜態的定義,容器是鏡像運行時的實體。** 容器可以被創建、啟動、停止、刪除、暫停等。
**容器的實質是進程**,但與直接在宿主執行的進程不同,容器進程運行于屬于自己的獨立的 [命名空間](https://en.wikipedia.org/wiki/Linux_namespaces) 。因此容器可以擁有自己的`root`文件系統、自己的網絡配置、自己的進程空間,甚至自己的用戶 ID 空間。
容器內的進程是運行在一個隔離的環境里,使用起來,就好像是在一個獨立于宿主的系統下操作一樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。也因為這種隔離的特性,很多人初學 Docker 時常常會混淆容器和虛擬機。
https://vuepress.mirror.docker-practice.com/basic_concept/container/
~~~
容器 = 鏡像 + 容器存儲層
~~~
> 鏡像是多層存儲,每一層是在前一層的基礎上進行的修改;而容器同樣也是多層存儲,是在以鏡像為基礎層,在其基礎上加一層作為容器運行時的存儲層。[利用 commit 理解鏡像構成 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/image/commit/)
> 除了鏡像依賴以外,還**需要注意的是容器對鏡像的依賴。** 如果有用這個鏡像啟動的容器存在(即使容器沒有運行),那么同樣不可以刪除這個鏡像。之前講過, **容器是以鏡像為基礎,再加一層容器存儲層,組成這樣的多層存儲結構去運行的。因此該鏡像如果被這個容器所依賴的,那么刪除必然會導致故障。** 如果這些容器是不需要的,應該先將它們刪除,然后再來刪除鏡像。[刪除本地鏡像 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/image/rm/#用-id、鏡像名、摘要刪除鏡像)
首層鏡像:
```shell
FROM scratch
ADD alpine-minirootfs-3.16.4-x86_64.tar.gz /
CMD ["/bin/sh"]
```
https://github.com/alpinelinux/docker-alpine/blob/106cf8fa24b495c3c7cac2ef3564fb78aef24751/x86_64/Dockerfile
https://raw.githubusercontent.com/alpinelinux/docker-alpine/106cf8fa24b495c3c7cac2ef3564fb78aef24751/x86_64/alpine-minirootfs-3.16.4-x86_64.tar.gz
https://hub.docker.com/layers/library/php/7.4.33-zts-alpine3.16/images/sha256-ec9045cb4e7388d81291499ae92bfdcf194644e8f701804a4592b6a8a2c400f0?context=explore
----
##### 數據卷
容器存儲層的生存周期和容器一樣,容器消亡時,容器存儲層也隨之消亡。因此,**任何保存于容器存儲層的信息都會隨容器刪除而丟失。**
按照 Docker 最佳實踐的要求,**容器不應該向其存儲層內寫入任何數據,容器存儲層要保持無狀態化。所有的文件寫入操作,都應該使用 數據卷(Volume)、或者 綁定宿主目錄**,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網絡存儲)發生讀寫,其性能和穩定性更高。
數據卷的生存周期獨立于容器,容器消亡,數據卷不會消亡。因此,**使用數據卷后,容器刪除或者重新運行之后,數據卻不會丟失。**
----
##### 使用 Dockerfile 定制鏡像
一般來說,應該會**將 `Dockerfile` 置于一個空目錄下,或者項目根目錄下。** 如果該目錄下沒有所需文件,那么應該把所需文件復制一份過來。如果目錄下有些東西確實不希望構建時傳給 Docker 引擎,那么可以用 `.gitignore` 一樣的語法寫一個 `.dockerignore`,該文件是**用于剔除不需要作為上下文傳遞給 Docker 引擎**的。https://vuepress.mirror.docker-practice.com/image/build/#鏡像構建上下文-context
----
##### 容器不是虛擬機
Docker 不是虛擬機,容器中的應用都應該以前臺執行,而不是像虛擬機、物理機里面那樣,用 systemd 去啟動后臺服務,容器內沒有后臺服務的概念。
然后發現容器執行后就立即退出了。甚至在容器內去使用 systemctl 命令結果卻發現根本執行不了。這就是因為沒有搞明白前臺、后臺的概念,沒有區分容器和虛擬機的差異,依舊在以傳統虛擬機的角度去理解容器。
對于容器而言,其啟動程序就是容器應用進程,**容器就是為了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出**,其它輔助進程不是它需要關心的東西。https://vuepress.mirror.docker-practice.com/image/dockerfile/cmd/
此外,當 Docker 容器中指定的應用終結時,容器也自動終止。https://vuepress.mirror.docker-practice.com/container/stop/
容器內并沒有除指定進程以外的其他進程,雖然在表現上很容易使人聯想到虛擬機,但至少在這點上,容器很明確的體現出了它和虛擬機最大的不同,**甚至拿輕量級的虛擬機來類比也是及其錯誤的,容器只是一個普通進程。**
~~~
可以看到在容器內是看不到除了主要進程以外的任何其它進程,這可以證明容器內并不是一個子系統
docker run -t -i ubuntu:18.04 /bin/bash
root@584e4a8dc01e:/# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 18504 2032 pts/0 Ss 09:48 0:00 /bin/bash
root 15 0.0 0.0 34400 1508 pts/0 R+ 09:49 0:00 ps -aux
root@584e4a8dc01e:/# top
top - 09:48:57 up 2:50, 0 users, load average: 0.00, 0.01, 0.05
Tasks: 2 total, 1 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.1 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 11690800 total, 10732624 free, 406416 used, 551760 buff/cache
KiB Swap: 3710972 total, 3710972 free, 0 used. 11020780 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 18504 2028 1620 S 0.0 0.0 0:00.03 bash
13 root 20 0 36616 1736 1308 R 0.0 0.0 0:00.00 top
~~~
----
##### Dockerfile 多階段構建
[多階段構建_嗶哩嗶哩_bilibili](https://www.bilibili.com/video/BV1Kg411D78F?p=15&vd_source=8fc0f668e63ab312d59a3089f3ca7a81)
> 多階段的每一階段都從 FROM 開始,**最終的 鏡像 只會從 最后一個階段構建,不會包含前面階段產生的層**,因此可以減少鏡像的體積。(就像預制菜可以直接由半成品加熱就可以吃,而不用買菜洗菜的環節)
[多階段構建 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/image/multistage-builds/#分散到多個-dockerfile)
https://github.com/khs1994-docker/laravel-demo
https://github.com/khs1994-docker/lnmp-nginx-conf-demo
file: app.go
```go
package main
import "fmt"
func main(){
fmt.Printf("Hello World!");
}
```
----
file: Dockerfile.one
```Dockerfile
FROM golang:alpine
RUN apk --no-cache add git ca-certificates
WORKDIR /go/src/github.com/go/helloworld/
# 將(上下文目錄中)源碼復制到容器中
COPY app.go .
RUN go get -d -v github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \
&& cp /go/src/github.com/go/helloworld/app /root
#1. 安裝依賴
#2. go build app
#3. app 復制到 /root
WORKDIR /root/
CMD ["./app"]
```
```shell
$ docker build -t go/helloworld:1 -f Dockerfile.one .
```
----
file: Dockerfile.build
```Dockerfile
FROM golang:alpine
RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld
# 將源碼復制到容器中build
COPY app.go .
RUN go get -d -v github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
```
file: Dockerfile.copy
```Dockerfile
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# 將(上下文目錄中)二進制構建物復制到容器中
COPY app .
CMD ["./app"]
```
file: build.sh
```shell
#!/bin/sh
echo Building go/helloworld:build
# 構建鏡像(go build)
docker build -t go/helloworld:build . -f Dockerfile.build
# 創建容器 extract
docker create --name extract go/helloworld:build
# 從容器 extract 中將 二進制構建物 app 復制出來
docker cp extract:/go/src/github.com/go/helloworld/app ./app
# 刪除容器 extract
docker rm -f extract
echo Building go/helloworld:2
# 構建鏡像(exec app)
docker build --no-cache -t go/helloworld:2 . -f Dockerfile.copy
rm ./app
```
```
$ chmod +x build.sh
$ ./build.sh
```
~~~
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
~~~
----
##### 編排
----
#### docker 安裝
~~~
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
~~~
~~~
sudo systemctl enable docker
sudo systemctl start docker
sudo systemctl status docker
docker info
docker run --rm hello-world
~~~
~~~
sudo systemctl daemon-reload
sudo systemctl restart docker
~~~
https://vuepress.mirror.docker-practice.com/install/
----
#### 自定義一個 oneinstack 鏡像
將自定義環境,文件,壓到鏡像上,做成鏡像發布。
----
#### 熱數據備份
將容器內修改的文件同步出來存放到物理機的存儲結構上
----
#### docker 命令說明
~~~
# https://wangdoc.com/bash/grammar
# 命令 選項 參數
command [option ...] [argument1 ... [ argumentN ]]
~~~
~~~
$: docker --help
用法:docker [OPTIONS] COMMAND
Options:
--config string 客戶端配置文件的位置(默認為"/root/.docker")。
-c, --context string 用于連接守護進程的上下文的名稱(覆蓋 DOCKER_HOST 環境變量和用 "docker context use " 設置的默認上下文)。
-D, --debug 啟用調試模式
-H, --host 列出要連接的守護進程套接字
-l, --log-level string 設置日志級別("debug"|"info"|"warning"|"error"|"fatal")(默認 "info")。
--tls 使用 TLS ;由-tlsverify暗示
--tlscacert string 只信任由該CA簽署的證書(默認為"/root/.docker/ca.pem")。
--tlscert string TLS 證書文件的路徑(默認為"/root/.docker/cert.pem")。
--tlskey string TLS 密鑰文件的路徑(默認為"/root/.docker/key.pem")
--tlsverify 使用 TLS 并驗證遠程
-v, --version 打印版本信息并退出
Management Commands:
app* Docker 應用程序(Docker公司,v0.9.1-beta3)。
builder 管理構建
buildx* Docker Buildx (Docker Inc., v0.9.1-docker)
compose* Docker Compose (Docker Inc., v2.12.2)
config 管理 Docker 配置
container 管理容器
context 管理語境
image 管理鏡像
manifest 管理 Docker 鏡像的清單和清單列表
network 管理網絡
node 理 Swarm 節點
plugin 管理插件
scan* Docker Scan(Docker公司,v0.21.0)。
secret 管理 Docker 的密鑰
service 管理服務
stack 管理 Docker 堆棧
swarm 管理 Swarm
system 管理 Docker
trust 管理 Docker 鏡像的信任
volume 管理卷
Commands:
attach 將本地標準輸入、輸出和錯誤流附加到正在運行的容器上
build 從 Docker 文件中建立一個鏡像
commit 從一個容器的變化中創建一個新的鏡像
cp 在容器和本地文件系統之間復制 文件/文件夾
create 創建一個新的容器
diff 檢查容器文件系統上的文件或目錄的變化
events 從服務器上獲取實時的事件
exec 在一個正在運行的容器中運行一個命令
export 將一個容器的文件系統導出為一個 tar 歸檔文件
history 顯示一個鏡像的歷史
images 列出鏡像
import 從一個 tar 包中導入內容以創建一個文件系統鏡像
info 顯示整個系統的信息
inspect 返回 Docker 對象的低層次信息
kill 殺死一個或多個正在運行的容器
load 從tar檔案或 STDIN 中加載一個鏡像
login 登錄到一個 Docker 注冊中心
logout 從 Docker 注冊中心注銷
logs 獲取一個容器的日志
pause 暫停一個或多個容器的所有進程
port 列出容器的端口映射或一個特定的映射
ps 列出容器
pull 從注冊表中拉出一個鏡像或一個存儲庫
push 將一個鏡像或版本庫推送到注冊中心
rename 重新命名一個容器
restart 重新啟動一個或多個容器
rm 移除一個或多個容器
rmi 移除一個或多個鏡像
run 在一個新的容器中運行一個命令
save 保存一個或多個鏡像到一個tar檔案(默認流向 STDOUT )。
search 在 Docker Hub 中搜索鏡像
start 啟動一個或多個停止的容器
stats 顯示容器資源使用情況的實時統計流
stop 停止一個或多個正在運行的容器
tag 創建一個指向 SOURCE_IMAGE 的標簽 TARGET_IMAGE
top 顯示一個容器的運行進程
unpause 取消一個或多個容器內的所有進程的停頓
update 更新一個或多個容器的配置
version 顯示 Docker 的版本信息
wait 阻塞直到一個或多個容器停止,然后打印它們的退出代碼
運行 docker COMMAND --help 可以獲得更多關于命令的信息。
要獲得更多關于 docker 的幫助,請查看我們的指南:https://docs.docker.com/go/guides/
通過 www.DeepL.com/Translator(免費版)翻譯
~~~
~~~
$: docker top --help
Usage: docker top CONTAINER [ps OPTIONS]
Display the running processes of a container
~~~
~~~
$: docker ps --help
Usage: docker ps [OPTIONS]
List containers
Options:
-a, --all Show all containers (default shows just running)
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print containers using a Go template
-n, --last int Show n last created containers (includes all states) (default -1)
-l, --latest Show the latest created container (includes all states)
--no-trunc Don't truncate output
-q, --quiet Only display container IDs
-s, --size Display total file sizes
~~~
----
### 初學者 docker 之疑問
**鏡像還可以指定不同的發行版操作系統嗎,那運行容器不就是在系統中又運行了一個系統?**
鏡像可以指定不同的發行版操作系統,是指可以指定某個發行版操作系統的 root 文件系統,也就是系統目錄結構文件等(各個發行版系統鏡像本身就是只有 rootfs 部分,不包含內核),并不是可以指定不同的操作系統內核版本,容器公用同一個宿主操作系統內核,所以容器的內核都是相同的版本。
容器是運行在宿主上的一個進程,并不是完整的系統或是子系統,這是和虛擬機最大的區別。不過對于容器進程來說,它是運行在一個隔離的系統資源內,這里使用的技術是 linux 自身的命名空間、組隔離等技術(想象一下編程語言中的命名空間,作用域隔離等技術),所以在容器內看起來就像是運行在一個獨立的系統中一樣,這種技術得益于 linux 底層的強大與靈活和開源社區的開放性。(據說 windows NT 比 linux 先進,可是 windows 上會誕生出 Docker 這樣的技術嗎?)
----
**應用在 docker 中運行會有性能損耗嗎?**
應用在容器內運行相較于系統原生的環境中運行會有性能損耗嗎,相信對性能有要求的應用都會首先關心這個問題。
[Docker容器、虛擬機和裸機運行的性能比較 - 極術社區 - 連接開發者與智能計算生態](https://aijishu.com/a/1060000000206531)
----
**容器只能運行“單一進程”?**
[為什么說容器是單進程模型_Docker_的博客-CSDN博客](https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/102028724)
[Docker容器的“單進程模型”](https://baijiahao.baidu.com/s?id=1673892417155737281&wfr=spider&for=pc)
[25 為什么說容器是個單進程模型-慕課專欄](https://www.imooc.com/read/84/article/2336)
> 針對上面這種 **將孤兒進程的父進程置為 1 號進程進而避免僵尸進程 處理方式,容器是處理不了的。** 進而就會導致**容器中在孤兒進程這種異常場景下僵尸進程無法徹底處理**的窘境。(**將孤兒進程的父進程設置為1號進程,是為了避免出現僵尸進程,這樣當孤兒進程退出后,由1號進程對其資源進行回收,防止出現對資源的永久占用**)
>
> 容器的單進程模型的本質其實是**容器中的 1號進程 并不具有 類 Unix 系統中 systemd 管理這些孤兒進程、多進程、多線程等復雜場景下的能力。**
單一進程,并不是指只有一個進程,而是指 一個 entrypoint 啟動進程(一號進程),其他線程都是一號進程的子進程。比如 nginx 和 apache 。
----
#### 為什么容器的主進程必須是前臺進程?
> 因為Docker容器僅在它的1號進程(PID為1)運行時,會保持運行。如果1號進程退出了,Docker容器也就退出了。[docker容器為啥一定要前臺運行 - luzhouxiaoshuai - 博客園](https://www.cnblogs.com/kebibuluan/p/15158793.html)
> Docker容器后臺運行,必須有一個前臺進程。容器運行的命令如果不是那些一直掛起的命令(比如運行ping,sleep),就是會自動退出的。
[docker容器中的前臺程序和后臺程序,為什么一定要前臺運行 - 騰訊云開發者社區-騰訊云](https://cloud.tencent.com/developer/article/2137830)
----
> 不知道為什么,似乎大家都對一些核心原理諱莫如深、只字不提、避而不談,官方口徑從不提鏡像的本質就是系統目錄結構這個基礎的事實,而軟件學習和理解的難點往往就在那些基礎的概念和原理上。如此簡單淺顯的原理,為什么要故作高深、諱莫如深呢,大家都默認皇帝穿了新裝,別問,別提,問就是傻子?提就是反叛者?
> 對初學者來說,不理解相關概念,靠自己的理解容易走偏。
[ubuntu18.04的docker基礎鏡像_dockerubuntu18.04,dockerubuntu18.04鏡像-Ubuntu工具類資源-CSDN文庫](https://download.csdn.net/download/yunfwe/10766980?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165214483316781435469461%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165214483316781435469461&biz_id=1&utm_medium=distribute.pc_search_result.none-task-download-2~all~first_rank_ecpm_v1~rank_v31_ecpm-5-10766980-null-null.142^v9^control,157^v4^control&utm_term=ocker%E9%95%9C%E5%83%8F%E5%BF%85%E9%A1%BB%E5%8C%85%E5%90%AB%E7%B3%BB%E7%BB%9F%E5%90%97)
> 鏡像大小僅26M,包含完整的ubuntu18.04.1基礎系統,可以通過apt-get命令更新和安裝其他軟件包,使用docker load -i ubuntu\_18.04-image.tar.gz 來加載鏡像
[docker容器的分層思想_dianlv8134的博客-CSDN博客](https://blog.csdn.net/dianlv8134/article/details/101369993?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-3-101369993-blog-120147021.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-3-101369993-blog-120147021.pc_relevant_default&utm_relevant_index=6)
~~~
bootfs : kernel boot
rootfs : /etc /dev /bin /usr ..
容器的內核會映射到容器的rootfs,等啟動到bootfs的時候,容器就會卸載掉rootfs,由系統的rootfs也就是kernel進行支持,而bootfs的目錄結構就會很小,所以容器就會很小。
所有的容器無法對kernel進行升級,如果安裝的環境需要其他的版本的內核,則不能安裝在docker容器中,需要放在虛擬機中運行,對kernel沒限制的則可以使用docker容器運行。
~~~
[再探docker容器的鏡像分層和私有倉庫_咸魚王變身的博客-CSDN博客](https://blog.csdn.net/qq_41257472/article/details/120147021?ops_request_misc=&request_id=&biz_id=102&utm_term=ocker%E9%95%9C%E5%83%8F%E5%BF%85%E9%A1%BB%E5%8C%85%E5%90%AB%E7%B3%BB%E7%BB%9F%E5%90%97&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-6-120147021.142^v9^control,157^v4^control)
~~~
### Docker 鏡像結構:
================================
contaier 容器層 讀寫層 ,在最頂層
================================容器層以下都是只讀 有四層結構構建而成
imageN
--------------------------------
....
--------------------------------
image0 如 scratch
--------------------------------kernel 軀干(文件系統)
aufs AUFS是一種聯合文件系統,實現了Docker鏡像的分層
--------------------------------
rootfs 就是各種不同的操作系統發行版,比如Ubuntu,Centos等等
--------------------------------
bootfs 主要是引導加載kernel, Linux剛啟動時會加載bootfs文件系統
--------------------------------
~~~
[docker鏡像是否包含操作系統? - 知乎](https://www.zhihu.com/question/366527646/answer/2280261145)
~~~
《現代操作系統》中有討論什么是操作系統,像常見的 windows,linux 這種操作系統就是運行在內核態的軟件。所謂內核態對下擁有對硬件的完全訪問權,對上能夠為用戶提供簡單統一的操作模型。
docker 主要是通過 namespace ,cgroup,aufs等 linux 內核提供的技術來完成資源的隔離,像 docker 鏡像本身就是一系列 aufs 層的打包。鏡像的釋放就是將 aufs 層釋放,系統訪問時會優先訪問上層的文件,使得底層的文件對系統不可見,僅此而已。
每一個 docker 容器都與 linux 宿主共享一個內核,容器里的操作還要靠速主機內核完成,很明顯光有 docker 容器是不能操作硬件的。
----
Docker鏡像包含操作系統,可以看一下Dockerfile相關的內容,熟悉一下打包Docker鏡像的流程。文件第一行就是“From \[system name\]”,system name替換成你想要作為基礎鏡像的鏡像名。至于后面的應用程序,tomcat,nginx等應用程序是在該基礎上添加進去的
追問一個:那FROM XXX(某發行版)中的那個XXX又是怎么來的![[為難]](https://pic1.zhimg.com/v2-132ab52908934f6c3cd9166e51b99f47.png)
其實就是一個與根文件系統類似的目錄結構用tar打包直接扔給docker import進來就好了,就這么簡單,甚至一個空目錄經過tar再import塞進docker能得到一個0k的鏡像(portainer用的那個基礎鏡像就是portainer官方自己打包的)
~~~
[docker鏡像是否包含操作系統_趙晗老師的博客-CSDN博客_docker鏡像必須包含系統嗎](https://blog.csdn.net/qfzhaohan/article/details/121794034)
> 你看到很多docker鏡像小,不是因為它們**不是完整的os**,而是因為**docker鏡像都是基于某個特定的目的精簡打包而成的**,去掉了很多兼容目的的安裝包、驅動、資源文件;最有名的就是alpine
[Docker為何需要OS的基礎鏡像?_krismile__qh的博客-CSDN博客_docker os](https://blog.csdn.net/krismile__qh/article/details/99883273)
> 它不是一個OS,**但為何需要OS的基礎鏡像?** 其實這里的**基礎鏡像是一個包含rootfs的鏡像。Kernel啟動后是需要把啟動文件解壓到rootfs上的,然后kernel找到init文件啟動就可以得到一個Linux環境了**,Docker做的事情就是模擬這個過程,讓kernel給出一個獨立的隔離環境。
[docker鏡像依賴于linux嗎,Docker鏡像是否跟操作系統相關的?還是跨平臺的?_weixin_29468871的博客-CSDN博客](https://blog.csdn.net/weixin_29468871/article/details/116893187?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-2-116893187-blog-121794034.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-2-116893187-blog-121794034.pc_relevant_antiscanv2&utm_relevant_index=5)
[理解Docker “容器主機”和“容器操作系統”的關系_小小鳥008的博客-CSDN博客_docker容器和宿主操作系統](https://blog.csdn.net/qq_36412715/article/details/118152467?spm=1001.2101.3001.6650.8&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-8-118152467-blog-99883273.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-8-118152467-blog-99883273.pc_relevant_aa&utm_relevant_index=15)
> 也稱為主機操作系統(Host OS),是Docker客戶端和Docker守護進程運行的**宿主操作系統**。
> 也稱為基礎操作系統(Base OS)。基礎操作系統是指包含操作系統(如Ubuntu、CentOS或windowsservercore)的鏡像。**注意,windows容器需要基礎操作系統,而Linux容器則不需要。**
[并非每個容器內部都能包含一個操作系統_Spring_java_gg的博客-CSDN博客](https://blog.csdn.net/u012516914/article/details/109476058?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-109476058-blog-118152467.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-109476058-blog-118152467.pc_relevant_paycolumn_v3&utm_relevant_index=2)
> 也就是說,所有的容器都依賴這一個內核了?比如我現在有一個需求,我的兩個容器運行在同一臺宿主機上,但是依賴的內核版本不一樣,或者需要配置的內核參數不一樣,怎么解決呢?**解決不了,這也是容器化技術相比于虛擬機的主要缺陷之一。**
> 實linux操作系統中代碼包含兩部分,**一部分是文件目錄和配置,另外一部分是內核**,這兩部分是分開存放的,**系統只有在宿主機開機啟動時才會加載內核模塊。說白了,即使鏡像中包含了內核也不會被加載。** 說到最后,原來**鏡像只是包含了操作系統的軀干(文件系統)**,并沒有包含操作系統的靈魂(內核)。
[整理了一份 Docker系統知識,從安裝到熟練操作看這篇就夠了|原力計劃](https://baijiahao.baidu.com/s?id=1668622380573288716&wfr=spider&for=pc)
> 而容器內的應用進程直接運行于宿主的內核,**容器內沒有自己的內核,而且也沒有進行硬件虛擬。** 因此容器要比傳統虛擬機更為輕便。**每個容器之間互相隔離,每個容器有自己的文件系統 ,容器之間進程不會相互影響**,能區分計算資源。
[Docker和宿主機操作系統文件目錄互相隔離的實現原理_汪子熙的博客-CSDN博客](https://jerry.blog.csdn.net/article/details/84206593?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-84206593-blog-118152467.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-84206593-blog-118152467.pc_relevant_paycolumn_v3&utm_relevant_index=1)
[Docker基礎知識](https://baijiahao.baidu.com/s?id=1711979845981138114&wfr=spider&for=pc)
> 容器基于鏡像啟動和運行,鏡像好比容器的源代碼,保存了用于啟動容器的各種條件,docker的鏡像是一個層疊的只讀文件系統。最底端是一個引導文件系統,即bootfs,docker用戶幾乎不會和引導文件系統有交互,當一個容器啟動后,它將會被移動到內存中,而引導文件系統將會被卸載,**docker鏡像的第二層是root文件系統rootfs(ubuntu),位于引導文件之上,root文件系統可以是一種或多種的文件系統**,docker中root文件系統只能是只讀狀態,并且docker利用聯合加載的技術又會在root文件系統之上加載更多的只讀文件系統。聯合加載指的是一次加載多個文件系統,**但在外面看來只能看到一個文件系統。聯合加載會將各種文件系統疊加到一起。docker將這樣的文件系統稱之為鏡像。**
[Docker鏡像(image)詳解](http://c.biancheng.net/view/3143.html)
[docker鏡像依賴于linux嗎,Docker鏡像是否跟操作系統相關的?還是跨平臺的?_weixin_29468871的博客-CSDN博客](https://blog.csdn.net/weixin_29468871/article/details/116893187?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-2-116893187-null-null.pc_agg_new_rank&utm_term=docker%E9%95%9C%E5%83%8F%E5%8C%85%E6%8B%AC%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%90%97&spm=1000.2123.3001.4430)
[并非每個容器內部都能包含一個操作系統_Spring_java_gg的博客-CSDN博客](https://blog.csdn.net/u012516914/article/details/109476058)
[Docker中每個鏡像都有一個系統,會不會帶來極大的額外開銷_慕課猿問](https://www.imooc.com/wenda/detail/425702)
> docker容器的開銷并不是很大,遠比不上完整的操作系統。
> docker鏡像是**直接跑在宿主的內核上**的。 **比如alpine鏡像啟動才幾m而已。**
> docker用的是cgroup, 鏡像里運行的每個應用也是宿主的進程。
[Docker 制作基礎鏡像----打包操作系統_weixin_34318956的博客-CSDN博客](https://blog.csdn.net/weixin_34318956/article/details/91733368)
[阿里云Docker倉庫_imonkeyi的博客-CSDN博客_阿里云docker倉庫](https://blog.csdn.net/imonkeyi/article/details/120557675)
[容器虛擬化網絡漫談(上) - 專欄博客 / 開發者實踐 - RTC開發者社區-WebRTC中文論壇|RTC實時技術論壇](https://rtcdeveloper.agora.io/t/topic/23815)
> **docker 實際上是利用了多個 Linux 提供的特性來完成這一切,這也是當初 Docker 剛發布時被批評為「新瓶裝舊酒」的原因**,因為實際上 Docker 只是包裝了操作系統的能力并提供了一套易用的 API,并沒有發明什么新東西。 (除了底層芯片,上層的任何東西都只是新包裝而已,無法再憑空發明創造什么,但這樣的新瓶往往能掀起一場新的革命,帶來前所未有的效率革命。)
----
### 相關資源
https://hub.docker.com/_/scratch/
[Docker — 從入門到實踐 | Docker 從入門到實踐](https://vuepress.mirror.docker-practice.com/)
[?? Docker 簡介和安裝 - Docker 快速入門 - 易文檔](https://docker.easydoc.net/doc/81170005/cCewZWoN/lTKfePfP)
[微服務是什么? - 阮一峰的網絡日志](https://www.ruanyifeng.com/blog/2022/04/microservice.html)
[Docker 入門教程 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html)
[Docker教程:Docker入門實踐(精講版)](http://c.biancheng.net/docker/)
https://developer.aliyun.com/mirror/
[譯見 | 誰是 Docker 公司背后的神秘推手?-DaoCloud道客博客](http://blog.daocloud.io/5003.html)
> **Solomon Hykes: Docker 的使命就是為大眾的創新提供工具**
[云平臺核心 · 語雀](https://www.yuque.com/leifengyang/oncloud/vfvmcd)
[云原生實戰 - kubesphere](https://kubesphere.io/zh/learn/)
[Docker入門實戰完成 - kubesphere](https://kubesphere.io/zh/learn/level_1/lesson_25/video/)
[學習 Kubernetes 基礎知識 | Kubernetes - CN](https://kubernetes.io/zh-cn/docs/tutorials/kubernetes-basics/)
[在 Linux 上以 All-in-One 模式安裝 KubeSphere](https://kubesphere.io/zh/docs/v3.3/quick-start/all-in-one-on-linux/)
[還不了解Docker和k8s?6分鐘帶你快速了解! - 知乎](https://zhuanlan.zhihu.com/p/345798544)
~~~
盡管Docker為容器化的應用程序提供了開放標準,但隨著容器越來越多出現了一系列新問題:
如何協調和調度這些容器?
如何在升級應用程序時不會中斷服務?
如何監視應用程序的運行狀況?
如何批量重新啟動容器里的程序?
解決這些問題需要容器編排技術,可以將眾多機器抽象,對外呈現出一臺超大機器。現在業界比較流行的有:k8s、Mesos、Docker Swarm。
在業務發展初期只有幾個微服務,這時用 Docker 就足夠了,但隨著業務規模逐漸擴大,容器越來越多,運維人員的工作越來越復雜,這個時候就需要編排系統解救opers。
~~~
[10分鐘看懂Docker和K8S - 知乎](https://zhuanlan.zhihu.com/p/145428041)
> 就在Docker容器技術被炒得熱火朝天之時,大家發現,**如果想要將Docker應用于具體的業務實現,是存在困難的**——編排、管理和調度等各個方面,都不容易。于是,人們迫切需要一套管理系統,對Docker及容器進行更高級更靈活的管理。
[京東案例研究 | 庫伯內斯](https://kubernetes.io/case-studies/jd-com/)
> “我的建議是,首先你需要把這項技術和你自己的業務結合起來,其次你需要有明確的目標。你不能因為別人在用它就使用它。你需要考慮你自己的目標。”— 劉海峰,京東首席架構師
我的目標很簡單,解決單點故障問題,并能夠根據負載進行伸縮,實現“永不停機”。
[一文帶你了解容器技術的前世今生](https://mp.weixin.qq.com/s?__biz=MzkzNzI1MzE2Mw==&mid=2247484578&idx=1&sn=a8ae0d1c470351a8bbcb6891bae0ca23&chksm=c29304e6f5e48df010bc7a0ceefae80d01f440ca41a40930a40bcbcb12ce74799907a7d73ef5&token=1105111533&lang=zh_CN&scene=21#wechat_redirect)
> 然而令 James Bayer 沒有想到的是,短短幾個月 Docker 就迅速崛起了,崛起速度如此之快,快到 Cloud Foundry 以及所有的 PaaS 社區還沒來得及成為它的競爭對手,就直接被宣告出局了!
- 開始
- 公益
- 更好的使用看云
- 推薦書單
- 優秀資源整理
- 技術文章寫作規范
- SublimeText - 編碼利器
- PSR-0/PSR-4命名標準
- php的多進程實驗分析
- 高級PHP
- 進程
- 信號
- 事件
- IO模型
- 同步、異步
- socket
- Swoole
- PHP擴展
- Composer
- easyswoole
- php多線程
- 守護程序
- 文件鎖
- s-socket
- aphp
- 隊列&并發
- 隊列
- 講個故事
- 如何最大效率的問題
- 訪問式的web服務(一)
- 訪問式的web服務(二)
- 請求
- 瀏覽器訪問阻塞問題
- Swoole
- 你必須理解的計算機核心概念 - 碼農翻身
- CPU阿甘 - 碼農翻身
- 異步通知,那我要怎么通知你啊?
- 實時操作系統
- 深入實時 Linux
- Redis 實現隊列
- redis與隊列
- 定時-時鐘-阻塞
- 計算機的生命
- 多進程/多線程
- 進程通信
- 拜占庭將軍問題深入探討
- JAVA CAS原理深度分析
- 隊列的思考
- 走進并發的世界
- 鎖
- 事務筆記
- 并發問題帶來的后果
- 為什么說樂觀鎖是安全的
- 內存鎖與內存事務 - 劉小兵2014
- 加鎖還是不加鎖,這是一個問題 - 碼農翻身
- 編程世界的那把鎖 - 碼農翻身
- 如何保證萬無一失
- 傳統事務與柔性事務
- 大白話搞懂什么是同步/異步/阻塞/非阻塞
- redis實現鎖
- 淺談mysql事務
- PHP異常
- php錯誤
- 文件加載
- 路由與偽靜態
- URL模式之分析
- 字符串處理
- 正則表達式
- 數組合并與+
- 文件上傳
- 常用驗證與過濾
- 記錄
- 趣圖
- foreach需要注意的問題
- Discuz!筆記
- 程序設計思維
- 抽象與具體
- 配置
- 關于如何學習的思考
- 編程思維
- 談編程
- 如何安全的修改對象
- 臨時
- 臨時筆記
- 透過問題看本質
- 程序后門
- 邊界檢查
- session
- 安全
- 王垠
- 第三方數據接口
- 驗證碼問題
- 還是少不了虛擬機
- 程序員如何談戀愛
- 程序員為什么要一直改BUG,為什么不能一次性把代碼寫好?
- 碎碎念
- 算法
- 實用代碼
- 相對私密與絕對私密
- 學習目標
- 隨記
- 編程小知識
- foo
- 落盤
- URL編碼的思考
- 字符編碼
- Elasticsearch
- TCP-IP協議
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依賴注入
- 科目一
- 開發筆記
- 經緯度格式轉換
- php時區問題
- 解決本地開發時調用遠程AIP跨域問題
- 后期靜態綁定
- 談tp的跳轉提示頁面
- 無限分類問題
- 生成微縮圖
- MVC名詞
- MVC架構
- 也許模塊不是唯一的答案
- 哈希算法
- 開發后臺
- 軟件設計架構
- mysql表字段設計
- 上傳表如何設計
- 二開心得
- awesomes-tables
- 安全的代碼部署
- 微信開發筆記
- 賬戶授權相關
- 小程序獲取是否關注其公眾號
- 支付相關
- 提交訂單
- 微信支付筆記
- 支付接口筆記
- 支付中心開發
- 下單與支付
- 支付流程設計
- 訂單與支付設計
- 敏感操作驗證
- 排序設計
- 代碼的運行環境
- 搜索關鍵字的顯示處理
- 接口異步更新ip信息
- 圖片處理
- 項目搭建
- 閱讀文檔的新方式
- mysql_insert_id并發問題思考
- 行鎖注意事項
- 細節注意
- 如何處理用戶的輸入
- 不可見的字符
- 抽獎
- 時間處理
- 應用開發實戰
- python 學習記錄
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文檔相似度驗證
- thinkphp5.0數據庫與模型的研究
- workerman進程管理
- workerman網絡分析
- java學習記錄
- docker
- 筆記
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京東
- pc_detailpage_wareBusiness
- doc
- 電商網站設計
- iwebshop
- 商品規格分析
- 商品屬性分析
- tpshop
- 商品規格分析
- 商品屬性分析
- 電商表設計
- 設計記錄
- 優惠券
- 生成唯一訂單號
- 購物車技術
- 分類與類型
- 微信登錄與綁定
- 京東到家庫存系統架構設計
- crmeb
- 命名規范
- Nginx https配置
- 關于人工智能
- 從人的思考方式到二叉樹
- 架構
- 今日有感
- 文章保存
- 安全背后: 瀏覽器是如何校驗證書的
- 避不開的分布式事務
- devops自動化運維、部署、測試的最后一公里 —— ApiFox 云時代的接口管理工具
- 找到自己今生要做的事
- 自動化生活
- 開源與漿果
- Apifox: API 接口自動化測試指南