Docker 學習筆記(一):基礎命令

僅爲我的查閱使用,要學習 Docker 的話,推薦看這份文檔:《Docker — 從入門到實踐》nginx

P.S. 大多數的 docker container xxx/docker image xxx 命令,都有相對應的縮寫方式:docker xxxgit

零、安裝 docker

參見 《Docker — 從入門到實踐—安裝》,包括各 Linux 發行版、Windows、MacOSdocker

國內加速器: https://get.daocloud.io/#install-compose,包含 Linux 安裝加速、Hub 鏡像倉庫加速。(但它的 Windows 加速版本太老,別用)shell

1、基本概念

要構建並運行一個 Docker 容器,有這樣幾個步驟:ubuntu

  1. 編寫 Dockerfile,而後經過 build 命令從 Dockerfile 構建鏡像
    1. 鏡像是分層構建,分層存儲。這使得鏡像的複用、定製變的更爲容易。
    2. 鏡像不包含任何動態數據,其內容在構建以後就不會被改變。所以它對運維很友好,能夠實現一次 build 處處運行。
  2. 經過 run 命令啓動該容器。(鏡像倉庫後面再記)
    1. 鏡像內容是靜態的,而容器是動態的!
    2. 每個容器運行時,是以鏡像爲基礎層,在其上建立一個當前容器的存儲層。能夠稱這個爲容器運行時讀寫而準備的存儲層爲 容器存儲層
    3. 容器不該該向其存儲層內寫入任何數據,容器存儲層要保持無狀態化。
    4. 全部的文件寫入操做,都應該使用 數據卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網絡存儲)發生讀寫,其性能和穩定性更高。
  3. 用 login 命令登陸到 Docker 的鏡像倉庫(私人的或者公共的),而後經過 push 命令將構建好的鏡像推送上去。
  4. 在別的機器上 pull 鏡像下來,經過 docker run xxx 命令運行。

2、Docker 基礎命令

1. 獲取鏡像

經過 pull 命令從倉庫中獲取鏡像:緩存

# 格式
docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標籤]

# e.g. 1:從公共倉庫拉 nginx 的鏡像
# 下列兩條命令效果相同,默認從 library (官方鏡像)找鏡像,tag 默認爲 latest(最新版本)
docker pull library/nginx:latest
docker pull nginx

# e.g. 2:從公共倉庫中,拉取我的上傳的鏡像
docker pull <username>/myblog:latest

# e.g. 3:從私人倉庫拉取 ryan 項目下,名爲 myblog 的鏡像
docker login reg.myharbor.com:4321  # 私人倉庫通常都須要先登陸,會將登陸信息保存到本地
docker pull reg.myharbor.com:4321/ryan/myblog

本身編寫 Dockerfile,而後經過 Dockerfile 構建鏡像(Dockerfile 的語法後面再細說):bash

# --tag 能夠縮寫成 -t,用於指定鏡像的 [鏡像名:<tag>],其中 <tag> 可省略。
docker build --tag friendlyhello .  # 使用當前目錄下的 Dockerfile 構建鏡像,而且`鏡像名:tag`爲 `friendlyhello:latest`

2. 查看/刪除鏡像

查看鏡像列表:網絡

docker image ls -a     # 列出當前機器上的全部鏡像
docker images -a       # 上一條命令的縮寫

docker images -a <image name>  # 查找名爲 <image name> 的鏡像

刪除鏡像:運維

docker image rm <image id>
docker image rm <image name>:<tag>  # 刪除 <image name> 鏡像的一個 tag

docker rmi <xxx>  # `docker image rm <xxx>` 的縮寫

docker image ls -f dangling=true  # 列出全部虛懸鏡像(即倉庫名和 tag 都爲 none 的鏡像)
docker image prune  # 清除全部未被使用的虛懸鏡像(被依賴了的虛懸鏡像沒法直接清除,見後)

docker image rm $(docker image ls -a -q)  # 刪除本機的全部鏡像(危險操做)
docker system prune  # 刪除全部中止的容器+虛懸鏡像+未被使用 network+構建緩存
docker system prune --all # 除了上述數據以外,還要刪除全部未被容器使用的鏡像

若是一個正常的鏡像,或者某個容器依賴了某些虛懸鏡像,那這些虛懸鏡像就不能被直接刪除。你須要先刪除掉那個上層的鏡像或者容器。ssh

刪除該上層鏡像時,全部只被它依賴了的虛懸鏡像也會被自動清除掉。可是刪除上層容器後,還須要手動用 docker image prun 清除被它使用了的虛懸鏡像。

3. 啓動容器

  1. docker run: 從指定鏡像新建一個容器並運行命令,而後終止運行。標準流程以下:
    • 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載(對應 docker image pull
    • 利用鏡像建立並啓動一個容器(對應 docker container create
    • 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
    • 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
    • 從地址池配置一個 ip 地址給容器
    • 執行用戶指定的應用程序(對應 docker container start
    • 執行完畢後容器被終止(對應 docker container stop
# 在 ubuntu 18.04 中輸出 Hello World
# --rm 表示,容器終止運行後,自動刪除該容器
# 此外,還有 --env 設置環境變量,-p 設置端口映射,--volume 設置數據卷
# --net 設置網絡鏈接類型
docker run --rm ubuntu:18.04 /bin/echo 'Hello world'

docker run -it --user=root <image:tag> bash # 以 root 身份運行 bash(不要去用 su root,而後處處找 root 的密碼了。。)

# 進入容器的 bash 終端
# -i 使容器的 stdin 保持打開,-t 爲容器分配一個僞 tty。
# 結合使用上述兩個選項 `-it`,效果相似 ssh 遠程鏈接。
docker run -it ubuntu:18.04 /bin/bash

# P.S. 其實只須要 -i 參數,就能和容器進行交互了,敲命令能獲得回覆。
# -t 添加的僞終端,感受只是在每一個命令行開頭加了個 `root@25d5c233769b:/# ` 這樣的提示符。
  1. docker run -d:使新建的容器在後臺運行
# 在後臺啓動一個 nginx 容器,提供靜態網站訪問功能,或者作代理
# -d 表示在後臺運行該容器,--rm 使容器在終止後被自動刪除
docker run -d --rm my-nginx:latest

# --restart=always 容器意外退出時,老是自動重啓。以保證服務老是可用。
# --name my-blog  爲容器取個有意義的名字,可在任何命令中,用該名字替換 container id 使用
docker run --rm -d -restart=always --name my-blog my-nginx:latest

# 前臺運行的容器,stdout 會被定向到本機的 stdout,因此能直接看到命令的輸出
# 然後臺運行的容器,就須要經過下面的命令查看輸出了
docker logs <container id / container name>  # 查看指定容器的 logs,更詳細的參數請 man
docker logs -f <container id / container name>  # 持續地輸出容器的日誌(ctrl-c 退出)
  1. 查看容器列表、啓動/終止容器、刪除容器
docker container ls -a  # 列出全部容器
docker ps -a  # 上一條命令的縮寫

docker container create --name <container name>  <image>:<tag> [command]  # 從指定鏡像新建容器,可是不當即運行。

docker container start <container id / container name>   # 啓動一個已經終止運行的容器
docker container stop <container id / container name>   # 終止一個正在運行的容器(該容器可能在後臺工做,也多是正被別的 shell 運行)

docker container rm  <container id / container name>    # 刪除一個未運行的容器
docker container rm -f <container id / container name>   # 強制刪除容器,即便該容器正在運行

docker container prune  # 清理掉全部已終止的容器

docker [start|stop|rm] <xxx>  # 上述命令的縮寫,container 可省略
  1. 登入容器:
# 1. 使用 attach 命令登入(不推薦!!)
# 將容器的 stdin/stdout/stderr 與當前終端接駁,容器切換到前臺運行。
# 特別注意的是,由於容器切換到了前臺運行,退出會致使容器終止!所以纔不推薦用此命令。
docker container attach <container id / container name>`  # 可縮寫成 `docker attach xxx`

# 2. 使用 exec 命令登入(推薦方式)
docker exec -it <container id / container name> bash  # 使用默認用戶登陸
docker exec -it --user=root <xxx>  # 以 root 身份登入容器(不要去用 su root,而後處處找 root 的密碼了。。)
  1. 查看容器的各項數據
docker container stats  <container id / container name>  # 查看容器的 CPU/RAM 使用率,網絡IO速率等參數
docker container logs  <container id / container name>  # 查看容器日誌,通常都是 CMD/ENTRYPOINT 命令的日誌
docker container diff <container id / container name>   # 查看容器層相對鏡像的變更(A-added,D-deleted,C-changed)

docker container kill  <container id / container name>  # 強制終止容器,發送終止信號給容器。(只是發信號過去,不必定成功。。)

docker container ls --size  # 列出全部容器,顯示各容器的 disk 佔用

容器/鏡像中數據的導入和導出

# 1. 將容器中的指定路徑(文件夾) copy 出來
# 能夠指定存放路徑(若路徑不存在,會自動建立),也能夠經過管道以流的方式傳輸給下個程序
docker container cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-   
# 2. 將本機的數據拷貝進容器,能夠是路徑,也能夠經過管道以流的方式傳輸到容器中。(用 tar -ax 就能正確將流轉成原來的文件)
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

# 3. 存取鏡像中的數據
# 方法一:直接在 Dockerfile 中使用 COPY --from=<image name>:<tag> <src path> <dest path>
# 方法二:先使用 docker create 爲鏡像新建容器層,再用 docker cp 命令導入/導出數據。

4. 鏡像/容器的導入和導出

4.1 鏡像的導入導出

鏡像能夠經過中心倉庫進行分享,可是有些狀況下,咱們只想快速地將鏡像分享給某臺機器。這就須要用到鏡像的導入導出功能了:

# a. 將指定鏡像導出爲 tar 文件
# 注意:若是同名則會覆蓋(沒有警告)
docker save <imagename>:<tag> -o <filename>

# 使用 gzip 進一步壓縮
docker save <imagename>:<tag> | gzip > <imagename>-<tag>.tar.gz

# b. 從指定文件加載鏡像
docker load -i <imagename>-<tag>.tar.gz  # 不須要先解壓

上述導入導出命令,結合 ssh,就能完成鏡像的快速分享:

docker save <鏡像名> | bzip2 | pv | ssh <用戶名>@<主機名> 'cat | docker load'

# pv:即 Pipe Viewer,意思是經過管道顯示數據處理進度的信息。通常須要自行安裝。
# yay -S pv 或 sudo apt-get install pv 或 yum install pv

4.2 容器的導入和導出(不推薦)

容器導出後再導入到鏡像中,環境變量和一些基本的配置信息丟失了。因此最好仍是不用使用這個功能,先後不一致,從鏡像入手纔是正確的方式。

雖說容器層不該該保存任何動態數據,
可是總有特殊狀況(或者說太菜),咱們把一些必需的東西放進了容器層,如今要使容器能在另外一臺機器上運做。

這時候,就須要作容器的導入導出了:

# 將容器的當前快照導出爲文件
docker export [container id / container name] > ubuntu.tar

# 從文件將容器快照導入爲鏡像,
# 注意!!!是導入成了鏡像!而且爲這個鏡像指定了 [name:tag]
cat ubuntu.tar | docker import - test/ubuntu:v1.0

容器導出的鏡像,環境變量和一些基本的配置信息都會丟失,並且 ENTRYPOINT/CMD 信息也會丟失,運行(run)時還須要手動指定命令。

感受是至關很差用。

Docker 倉庫

docker login <repo-host:port>  # 登陸到指定的倉庫,默認登陸到 docker hub
docker logout <repo-host:port>   # 登出指定倉庫

docker search <image name>  # 在 Docker Hub 中搜索鏡像

參考

遇到過的問題

相關文章
相關標籤/搜索