Docker學習筆記(基礎篇)
前言
公司績效里面寫了要學習docker,其實平時用也會用,但是沒有系統的認知。
考慮到這個東西除了工作外,NAS和單子都有用到,就系統學一學吧。
下面是學習一本叫《第一本Docker書》的筆記。
另外因為成書的時間較早,需要一些外圍的資料補充才能跑現在的docker。
目標1:把單子的project打包到docker
目標2:把書看完
嗯,開始吧~
PS1:下面的所有操作都是基于Ubuntu的,緬懷一下已經沒了的Centos~
PS2:其實如果是用管理員登入的話就免去好多的sudo了~
一. Docker簡介
Docker優點
- 提供一個簡單、輕量的建模方式
- 職責的邏輯分離
- 快速、高效的開發生命周期
- 鼓勵使用面向服務的架構
Docker架構

- 鏡像是構建Docker世界的基石。
- 鏡像是Docker生命周期中的構建或打包階段,而容器則是啟動或執行階段。
- Docker借鑒了標準集裝箱的概念,不同的是:集裝箱運輸貨物,而Docker運輸軟件。
- 鏡像是分層的,你可以對其進行迅速的迭代。
二. Docker安裝
寫在最開始
下面是按照書上所說的做,最后是不行的,想要速度的請跳去這個鏈接
http://www.jeecms.com/hjdj/872.htm(2022-5-7親測可行)
或各大搜索引擎搜Ubuntu安裝docker
前提條件
#查看內核版本 uname -a #升級linux內核版本 sudo apt-get update sudo apt-get install linux-headers-3.8.0-27-generic linux-image-3.8.0-27-generic linux-headers-3.8.0-27 #更新Ubuntu Precise的啟動加載器 sudo update-grub #重啟電腦 sudo reboot
其實書本的Ubuntu才12,我的已經不知道多少了,反正就是很高了。
所以上面的代碼其實作用不大,但是為什么還要保留下來呢?
可能我覺得安裝任何軟件之前先確定系統版本是必要步驟吧~
go on~
#檢查Device Mapper ls -l /sys/class/misc/device-mapper #如果沒裝那么 sudo modprobe dm_mod #添加Docker的ATP倉庫 sudo sh -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
開始安裝
#檢查有沒有裝curl whereis curl #沒有的話就安裝他 sudo apt-get -y install curl #添加Docker倉庫的GPG密鑰 curl -s https://get.docker.io/gpg | sudo apt-key add - #更新APT源 sudo apt-get update #在Ubuntu中安裝Docker sudo apt-get install lxc-docker #確認docker已經安裝 sudo docker info
好了,按照這個書上說的已經裝不了~ 哈哈哈哈哈哈哈
這個時候就去問問度娘咯~ 參考:http://www.jeecms.com/hjdj/872.htm 可以了。
總結如下:
#更新apt軟件包索引并安裝軟件包以允許apt通過HTTPS使用存儲庫 sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common #添加 Docker 的官方 GPG 密鑰 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - #查看當前系統架構 dpkg --print-architecture #根據架構選用以下對應命令執行: #amd64: sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" #armhf: sudo add-apt-repository "deb [arch=armhf] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" #arm64: sudo add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" #安裝DOCKER引擎 sudo apt-get install docker-ce docker-ce-cli containerd.io #列出可用版本 apt-cache madison docker-ce #安裝指定版本 sudo apt-get install docker-ce=<版本號> docker-ce-cli=<版本號> containerd.io #我的就是 sudo apt-get install docker-ce=5:20.10.15~3-0~ubuntu-focal docker-ce-cli=5:20.10.15~3-0~ubuntu-focal containerd.io #驗證是否安裝成功 sudo docker run hello-world
功成~
Docker守護進程
配置docker的訪問端口,這個端口設置之后外面的人就可以通過這個端口訪問了。
因為這個是沒有認證的,這樣就很危險了,所以需要這個叫TLS認證的東西去把把關。
當然也可以用防火墻來做~
#配置docker守護進程的網絡 export DOCKER_HOST="tcp://0.0.0.0:12345" #查看進程狀態 systemctl status docker #關閉進程 systemctl stop docker #開啟進程 systemctl start docker
docker的進程管理其實用systemctl就好了,書里面的不知道是啥,反正用不鳥~
三. Docker入門
確保Docker已經就緒
#確保docker就緒 sudo docker info
鏡像相關
書本是直接就創建容器了,但是所有容器都是基于鏡像的。
所以我覺得有必要在這里補一下鏡像的基礎部分。
參考網址:https://www.csdn.net/tags/MtTaEgxsOTM3NDItYmxvZwO0O0OO0O0O.html
關于鏡像的系統認知請看第四部分~
要點:
- 鏡像的話可以去docker hub上面找(https://hub.docker.com/)
- 如果鏡像被容器使用了,原則上來說是要先刪容器再刪鏡像的,但是可以用-f來強制刪除
#拉取鏡像,默認拉最新的,可以直接run,如果沒有run會自己拉鏡像的 sudo docker pull ubuntu #查看拉取了的所有鏡像 sudo docker images --digests #修改鏡像庫地址 vi /etc/docker/daemon.json #輸入 { "registry-mirrors": ["https://3laho3y3.mirror.aliyuncs.com"] } #刪除鏡像 [OPTIONS] 中 -f 表示強制刪除 sudo docker rmi [OPTIONS] IMAGE [IMAGE…] #通過短ID刪除,這個代表鏡像id以14f6開頭的鏡像,一般而言,前四位可以唯一標志,如果不可以,docker會提示的 sudo docker rmi 14f6 #通過鏡像長ID刪除 sudo docker rmi 14f60031763d #通過鏡像名刪除 sudo docker rmi ubuntu:latest #通過鏡像的digest刪除 sudo docker rmi > ubuntu@sha256:84c334414e2bfdcae99509a6add166bbb4fa4041dc3fa6af08046a66fed3005f #刪除所有叫redis的鏡像 sudo docker rmi $(docker images –q redis) #刪除所有鏡像 sudo docker rmi $(docker images –qa)
創建容器
搞了這么久終于可以創建容器了,要點有:
- 可以使用docker run指令創建容器;
- docker run提供了容器從創建到啟動的功能;
- -i 表示保證容器中STDIN是開啟的,表示shell接受標準輸入;
- -t 表示docker為創建的容器分配一個偽tty終端;
#創建容器 sudo docker run -i -t ubuntu /bin/bash
使用容器
因為安裝的是最簡的Ubuntu,所以好多包都沒有默認裝上
#列出所有容器 sudo docker ps -a #列出最后一次運行的容器 sudo docker ps -l #----- 容器內 ----- #查看主機名 hostname #查看容器的host cat /etc/hosts #更新軟件庫 apt-get update #安裝查看網絡狀態的包 apt-get install -y iproute2 #查看容器接口 ip a #退出容器 exit #或者 ctrl + D #----- 容器內 -----
容器命名
- 命名規則:[a-zA-Z0-9_.-]
- 命名必須唯一
#容器命名 sudo docker run --name test_sys -i -t ubuntu /bin/bash #容器改名 sudo docker rename <舊容器名|舊容器id> <新容器名> #ex:把abc的容器改名為cba sudo docker rename abc cba
啟停容器
- 無論停止或者啟動都不會進入容器內部;
- stop向容器內發送SIGTERM信號,相當于關機;
- kill向容器內發送SIGKILL信號,相當于斷電;
#啟動容器 sudo docker start <容器名|容器ID> #重啟容器 sudo docker restart <容器名|容器ID> #停止容器 sudo docker stop <容器名|容器ID> #如果想快速停止某個容器,那么: sudo docker kill <容器名|容器ID>
附著到容器
上面的啟動或者停止都不會進入容器,如果想再次進入那么就需要:
- 停止的容器附著不了,需要啟動了才能附著;
- 附著后如果退出,則容器也會停止運行;
#附著到容器 sudo docker attach <容器名|容器ID>
創建守護式容器(daemonized container)
- 上面那些都是交互式運行的容器(interactive container);
- 守護式容器沒有shell,適合運行應用程序和服務;
#創建守護式容器,并且跑一個sh,每5秒輸出一個hello world sudo docker run --name test_dc -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 5; done"
查看容器日志
- 進入日志模式之后按 ctrl + c 退出;
#查看日志 sudo docker logs <容器名|容器ID> #跟蹤日志 sudo docker logs -f <容器名|容器ID> #加入時間戳 sudo docker logs -ft <容器名|容器ID> #獲取最新的1000行 sudo docker logs -ft --tail 1000 <容器名|容器ID>
容器內進程
- 使用exec指令,exec是docker1.3引入的,1.3之前看nsenter指令;
- 相當于直接在容器內執行后面的指令了;
- 退出交互式任務不會停止運行docker;
#查看容器內進程 sudo docker top <容器名|容器ID> #運行容器內進程(后臺任務),在etc下新建一個叫test的文件 sudo docker exec -d <容器名|容器ID> touch /etc/test #運行容器內進程(交互式任務) sudo docker exec -t -i <容器名|容器ID> /bin/bash
容器的自重啟
--restart的值及含義:
- no 默認策略,在容器退出時不重啟容器
- on-failure 在容器非正常退出時(退出狀態非0),才會重啟容器
- on-failure:n 在容器非正常退出時重啟容器,最多重啟n次
- always 在容器退出時總是重啟容器(掛web服務的時候就比較有用了)
#創建一個自重啟的容器 sudo docker run -d --restart=always --name <容器名> <鏡像名> #設置一個已經存在的容器自動重啟 sudo docker update --restart=always <容器名|容器ID> #當退出代碼為非0時才重啟 sudo docker update --restart=on-failure <容器名|容器ID> #當退出代碼為非0時才重啟,并且限制重啟次數為5次 sudo docker update --restart=on-failure:5 <容器名|容器ID>
獲取容器詳情
- /var/lib/docker 放著所有docker的鏡像、容器以及容器的配置;
- /var/lib/docker/containers放著容器;
#通過inspect獲取更多容器信息 sudo docker inspect <容器名|容器ID> #有選擇的取容器信息,比如容器運行狀態 sudo docker inspect --format='{{.State.Running}}' <容器名|容器ID>
刪除容器
禁術總是留到最后
#刪除容器 sudo docker rm <容器名|容器ID> #刪除所有容器 sudo docker stop $(docker ps -a -q) sudo docker rm $(docker ps -a -q)
四. Docker鏡像和倉庫
前言
我也不是很明白為什么先說的容器,再說的鏡像~
anyway~
這里就會有對鏡像的絕大部分操作了~
是什么Docker鏡像

- 簡單來說Docker鏡像就是一個只讀的文件系統
- 以一個叫聯合加載技術(union mount)實現疊(套)加(娃)
- 當需要對容器里面的只讀系統進行寫操作時,會復制一個副本到讀寫層,原來的只讀系統是不會發生變法的,這個叫寫時復制(copy on write)
- 感性點說:一個容器只有一個基礎鏡像,基礎鏡像里面可以裝docker,加載其他鏡像(套娃)
列出鏡像
- 鏡像保存在倉庫中,從倉庫下載下來;
- 而倉庫存在于Registry中,默認的Registry是由Docker公司運營的公共Registry服務,即Docker Hub;
- Docker Registry的代碼是開源的,可以運行自己私有的Registry服務;
#列出Docker鏡像 sudo docker images #查看docker占用系統空間 docker system df
拉取鏡像
- 書本上的pull指令默認會拉所有,但現在的pull默認只拉最新的;
- 鏡像下載下來后默認保存在:/var/lib/docker 目錄下面;
- 查看倉庫中鏡像的所有tags -- 瀏覽器打開:"${Registry地址}/${鏡像名}/tags",例子:https://registry.hub.docker.com/v1/repositories/ubuntu/tags;
#默認拉取最新的鏡像 sudo docker pull ubuntu #拉取指定tag的鏡像 sudo docker pull ubuntu:22.10
查找鏡像
- 可以通過docker search指令來查找所有Docker Hub上的公共可用鏡像
- 查找回來的內容包括:倉庫名、鏡像描述、用戶評價(stars)、是否官方(Official)、是否構建(Automated,是否走了Docker Hub的構建流程)
#查找鏡像 sudo docker search ubuntu
構建鏡像
好了,到戲玉了
- 構建docker的兩種方法:1. docker commit指令;2. docker build指令 + Dockerfile文件;
- 一般不推薦用docker commit來構建了;
- 一般來說我們不是真正的創建新鏡像,而是基于一個基礎鏡像去構建新鏡像;
- 如果想從零開始,參考:https://docs.docker.com/develop/develop-images/baseimages/;
- Docker Hub相當于Git Hub,共有的,上了的話隨便一個人都能下載下來看;
#登錄Docker Hub sudo docker login
構建鏡像-commit
- 當我們運行一個容器的時候(如果不使用卷的話),我們做的任何文件修改都會被記錄與容器存儲層里。而Docker提供了一個docker commit 的命令,可以將容器的存儲層保存下來成為鏡像。換句話說,就是在原有鏡像的基礎上,在疊加上容器的存儲層,并構成信的鏡像,以后我們運行這個新鏡像的時候,就會擁有原有容器最后的文件變化。
- 除了學習之外,docker commit還有一些特殊的應用場合,比如被入侵后保存現場等;
- 如果在安裝軟件,編譯構建,那會有大量的無關內容被添加進來,如果不小心清理,將會導致鏡像及其臃腫。
- commit出來的鏡像是黑箱鏡像,雖然docker diff或許可以得到一點線索,但是遠遠不到可以確保生成一致鏡像的地步。
- 任何修改的結果僅僅是在當前層進行標記,添加,修改,而不會改動上一層。
- 其實我個人覺得commit挺好用的~ 黑盒就黑盒啊~ 讓你知道那么多干嘛~ 哈哈哈哈哈哈~
#使用commit創建鏡像 sudo docker commit [選項] <容器名|容器ID> [<倉庫名>[:<標簽>]] #-m:提交描述,--author:作者名,Ex: sudo docker commit -m="加入test.json文件" --author="GSSSL" ubuntu gssl/ubuntu_test_file:test #查看提交記錄 sudo docker history <容器名|容器ID> #查看容器的修改記錄 sudo docker diff <容器名|容器ID>
導入導出鏡像
- 其實鏡像還能支持導入導出的,這樣初期就可以繞開版本庫了;
#鏡像導出 sudo docker save -o <鏡像導出路徑及文件名> <鏡像名|鏡像ID> #ex: sudo docker save -o /home/gssl/download/test_image.tar ubuntu/latest #鏡像導入 sudo docker load --input <鏡像導入路徑及文件名> #ex: sudo docker load --input /home/gssl/download/test_image.tar
構建鏡像-Dockerfile
- Dockerfile 是一個文本文件,其內包含了一條條的 指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。
FROM指定了 基礎鏡像,因此一個Dockerfile中FROM是必備的指令,并且必須是第一條指令。- Docker 還存在一個特殊的鏡像,名為
scratch。這個鏡像是虛擬的概念,并不實際存在,它表示一個空白的鏡像。 - scratch適合不以任何系統為基礎,直接將可執行文件復制進鏡像。
- RUN指令的執行形式有兩種:shell 格式:
RUN <命令>和 exec 格式:CMD ["可執行文件", "參數1", "參數2"] - 一個RUN指令就算一層鏡像,Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過 42 層,現在是不得超過 127 層。
- 使用
&&將各個所需命令串聯起來,Dockerfile 支持 Shell 類的行尾添加\的命令換行方式,以及行首#進行注釋的格式。 - 如果發現標準輸入的文件格式是
gzip、bzip2以及xz的話,將會使其為上下文壓縮包,直接將其展開,將里面視為上下文,并開始構建。
#----- Dockerfile ----- FROM debian:stretch RUN set -x; buildDeps='gcc libc6-dev make wget' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDeps #清除緩存 #----- Dockerfile ----- #build鏡像 sudo docker build [選項] <鏡像名>:<TAG_ID> <上下文路徑/URL/-> #ex: sudo docker build -t test_image:1.0 .
Dockerfile 指令
- CMD - 用于指定一個容器啟動時要運行的指令;
- CMD - docker run可以覆蓋CMD的指令;
- CMD - Dockerfile中只能指定一條CMD指令,若指定多條只執行最后一條;
- ENTRYPOINT - 跟CMD一樣,但默認docker run不會覆蓋;
- ENTRYPOINT - 如果docker run想覆蓋,那么加入--entrypoint即可
- RUN - 指定鏡像被構建時要運行的指令;
- WORKDIR - 當從鏡像創建一個新容器時,在容器內部設置一個工作目錄,ENTRYPOINT、/、CMD都會在這個目錄下執行;
- ENV - 在鏡像構建過程中設置的環境變量;
- ENV - ENV <變量名> <值>,調用:$<變量名>
- USER - 指定該鏡像以什么樣的用戶去運行;
- USER - docker run時可以用-u覆蓋;
- VOLUME - 用來向基于鏡像創建的容器添加卷;
- VOLUME - 關于卷有以下幾個特性:
- 卷可以再容器間共享和重用;
- 一個容器可以不是必須和其他容器共享卷;
- 對卷的修改是即時生效的;
- 對卷的修改不會對更新鏡像產生影響;
- 卷會一直存在直到沒有任何容器使用它;
- VOLUME - 可以用來測試容器和內部代碼、管理日志、或者處理容器內數據庫?
- ADD - 用來將構建環境下的文件和目錄復制到鏡像中,源是文件夾的話會把文件夾整個拷過去。
- ADD - ADD <源文件|源路徑|URL> <目標文件|目標路徑>
- ADD - ADD源文件是歸檔文件(就是壓縮包)的話,會自動解壓到目標目錄,相當于-x的tar指令;
- ADD - 如果目標路徑不存在,那么會創建這個全路徑;
- ADD - ex: ADD xx.js /opt/app/xx.js #把xx.js寫入到xx.js里面
- ADD - ex:ADD xx.tar /opt/app #把xx.tar解壓縮到目標目錄下
- COPY - 跟ADD類似,但COPY只關心再構建上下文復制本地文件,而不提取或解壓。源是文件夾的話會把文件夾下所有內容拷過去;
- COPY - COPY <源文件|源路徑|URL> <目標文件|目標路徑>
- COPY - 目標目錄不在Docker會自動創建目錄結構,類似mkdir -p那樣
- ONBUILD - 能為鏡像添加觸發器(trigger)。當一個鏡像被用作其他鏡像的基礎鏡像時,該鏡像中的觸發器將會被執行。
- ONBUILD - 一般跟在FROM之后,觸發器后可以跟任何指令。
- ONBUILD - ONBUILD ADD ./app/src
- ONBUILD - 就是ONBUILD指定的操作只會在創建子鏡像的時候執行一次,基于這個子鏡像做的孫子鏡像是不會再執行了
私有倉庫
決定在構建鏡像之前先把私庫給搞好先;
Docker Hub上的鏡像都是公家的,如果不想公開,那么就要做一個私有倉庫了;
參考以下鏈接:
https://yeasy.gitbook.io/docker_practice/repository/registry
https://cloud.tencent.com/developer/article/1718368
docker run -d -p 5000:5000 -v /data/my_docker_registry/registry:/var/lib/registry -v /data/my_docker_registry/config.yml:/etc/docker/registry/config.yml --name my_docker_registry registry
要轉圖形圖像方面的學習了,docker就暫時到這里吧~~
其實就差docker-compose、私庫部署這兩塊了~ 后面有時間再補吧~

浙公網安備 33010602011771號