斷斷續續的使用Docker好幾年了,但是一直沒有全面深入的去了解過,每次用到都是Google一下相關的命令解決臨時的問題,到頭來卻毫無收獲。好在,我終於意識到了這個問題,便決定從頭開始,耐心的學學Docker,並把學習過程記錄下來,方便以后參考,也望與大家交流學習。
本人比較偏愛Ubuntu,故本文所用命令皆基於Ubuntu 16.04,其他版本的命令會有稍有不同,本文不多做介紹。
目錄
簡介
容器:將軟件打包成標准化單元,以用於開發、交付和部署,而 Docker 是世界領先的軟件容器平台。
容器鏡像是輕量的、可執行的獨立軟件包,包含軟件運行所需的所有內容:代碼、運行時環境、系統工具、系統庫和設置。
容器 VS 虛擬機:
容器和虛擬機具有相似的資源隔離和分配優勢,但功能有所不同,因為容器虛擬化的是操作系統,而不是硬件,因此容器更容易移植,效率也更高。
-
容器是一個應用層抽象,用於將代碼和依賴資源打包在一起。多個容器可以在同一台機器上運行,共享操作系統內核,但各自作為獨立的進程在用戶空間中運行。與虛擬機相比,容器占用的空間較少(容器鏡像大小通常只有幾十兆),瞬間就能完成啟動。
-
虛擬機 (VM) 是一個物理硬件層抽象,用於將一台服務器變成多台服務器。管理程序允許多個 VM 在一台機器上運行。每個 VM 都包含一整套操作系統、一個或多個應用、必要的二進制文件和庫資源,因此占用大量空間。而且 VM 啟動也十分緩慢。
安裝
准備
首先更新Package索引:
sudo apt-get update
添加Https支持:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common -y
然后添加Docker官方的GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
## 如果上面的地址不能下載,可以使用國內鏡像
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
添加Docker-CE穩定版倉儲地址:
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"
由於Docker官方倉儲download.docker.com
的訪問較慢,故使用了中科大鏡像源替代。
安裝
最后,便可以直接安裝了:
sudo apt-get update
sudo apt-get install docker-ce
我們可以運行一下Hello Word
來驗證一下是否安裝成功:
sudo docker run hello-world
默認情況下,Docker需要使用root身份來訪問,每次都使用sudo
命令較為麻煩,我們可以將當前用戶添加到docker
用戶組來實現非root用戶訪問:
sudo usermod -aG docker $USER
重新登錄一下,便可以不使用sudo
命令來操作docker了。
鏡像加速
默認情況下,Docker鏡像是從Docker官方市場store.docker.com
來拉取的,同樣非常緩慢,好在Docker官方提供了國內鏡像庫,可使用如下命令來配置:
docker --registry-mirror=https://registry.docker-cn.com daemon
為了永久性保留更改,可以修改/etc/docker/daemon.json
文件並添加上 registry-mirrors 鍵值:
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
修改保存后重啟 Docker 以使配置生效:
sudo systemctl restart docker
安裝Docker Compose
Docker Compose 是一個用來定義和運行復雜應用的Docker工具。我們的應用通常會由多個容器組成,使用Docker Compose可以非常容易的將一組容器當成一個整體來配置部署。
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
可以在 https://github.com/docker/compose/releases 查看具體的發布列表。
常用命令
運行容器(run)
run是我們最常用的命令:
docker run nginx
如上,便啟動了一個nginx
容器。
端口映射(-p)
此時,我們還無法通過訪問宿主機的IP來訪問剛才部署的Nginx,需要先進行端口映射:
docker run -p 8080:80 nginx
后台運行(-d)
默認情況下,當我們推出命令行時,容器也會被關閉。我們可以使用-d
參數使容器保持后台運行:
docker run -d <image-name>
然后訪問宿主機的IP:8080,便可以看到“Welcome to nginx!”。
指定名稱(-n)
docker run --name <container-name> <image-name>
docker run --name myredis redis
如上,創建了一個名稱為redis
的容器。
持久化數據(-v)
容器被設計為無狀態的,當我們刪除一個容器時,保存在其中的數據也會隨之刪除。如果我們希望某些數據不隨着容器的刪除而刪除,則可以使用目錄綁定(通常稱為卷),將容器中的某個文件夾於主機上的文件夾綁定,來實現數據的持久化。
docker run -v <host-dir>:<container-dir> <image-name>
除此之外,我們還可以使用Data Containers
來實行數據的持久化,數據容器(Data Containers)唯一的職責就是存儲和管理數據:
docker create -v /config --name dataContainer busybox
如上,我們使用busybox
鏡像創建了一個數據容器,並使用-v
參數來指定容器存儲和管理數據的目錄位置。
然后我們可以將文件拷貝到容器中:
docker cp config.conf dataContainer:/config/
接下來,我們就可以在新的容器中引用該數據容器了:
docker run --volumes-from dataContainer ubuntu
新創建的ubuntu
容器掛載了數據容器的/config
目錄。
重啟策略(--restart)
通過--restart
選項,可以設置容器的重啟策略,以決定在容器退出時Docker守護進程是否重啟剛剛退出的容器。
docker run -d --restart=always <image-name>
有如下4種重啟策略:
- no,默認策略,在容器退出時不重啟容器
- on-failure,在容器非正常退出時(退出狀態非0),才會重啟容器
- on-failure:3,在容器非正常退出時重啟容器,最多重啟3次
- always,在容器退出時總是重啟容器
- unless-stopped,在容器退出時總是重啟容器,但是不考慮在Docker守護進程啟動時就已經停止了的容器
進入交互模式(-it)
docker run -it [image-name] /bin/bash
- -i interact 進入交互模式。
- -t tty 分配一個偽終端。
執行之后,可以看到命令行的主機名已經變成了容器的Id,表示成功進入到了容器中,可以使用exit
命令退出容器。
其他
# 啟動一個SQLServer容器
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Qwer1234' -p 1433:1433 -d --restart=unless-stopped microsoft/mssql-server-linux
管理容器
查看容器(ps)
docker ps
通過ps
命令可以看到當前運行的容器,添加-a
參數,則可以看到停止的容器。
我們可以使用docker inspect <friendly-name|container-id>
來查看某個容器的詳細信息:
dokcer inspect redis
附加容器(attach)
ttach可以附加到一個已經運行的容器的stdin中。
docker attach [containerid]
進入容器(exec)
docker exec -it [containerid] /bin/bash
是需要注意的是,對於attach
,如果從這個stdin中exit,會導致容器的停止。而exec
則不會,推薦使用exec
。
停止容器(stop)
docker stop [containerid]
刪除容器(rm)
docker rm [containerid]
如果要刪除的容器正在運行,則無法刪除,可以添加-f
參數來強制刪除,也可以先停止容器再刪除:
如果我們想刪除所有的容器,可以使用如下命令:
docker rm $(docker ps -a -q) -f
鏡像管理
Docker把應用程序及其運行環境等打包在 image 文件里面,相當於容器的模板。
搜索鏡像
我們可以在 registry.hub.docker.com 查找鏡像,也可以使用 dokcer search <name>
命令來搜索,如:我們使用如下命令來搜索redis
鏡像。
docker search redis
查看鏡像
# 查看鏡像列表
docker images
# 查看所有鏡像(包括中間層鏡像)
docker image -a
# 查看所有鏡像的ID
docker images -q
# 查看所有的虛懸鏡像(-f 顯示滿足條件的鏡像)
docker images -f "dangling=true"
# 按倉庫名過濾
docker images [REPOSITORY]
# 按倉庫名和標簽過濾
docker images [REPOSITORY:TAG]
鏡像列表輸出如下:
REPOSITORY | TAG | IMAGE ID | CREATED | SIZE |
---|---|---|---|---|
hello-world | latest | e38bc07ac18e | 2 weeks ago | 1.85kB |
每列含義:
- REPOSITORY:倉儲名
- TAG:標簽, 一個鏡像可以有多個標簽
- IMAGE ID:鏡像的唯一標識,通常在刪除鏡像時使用
- CREATED:創建時間
- SIZE:所占用的空間,展開后的各層所占空間的總和。
刪除鏡像
# 刪除鏡像
docker rmi [imageid]
docker image rm [imageid]
# 刪除所有鏡像
docker image rm $(docker images -q) -f
# 刪除虛懸鏡像(dangling image)
docker image prune
倉庫名和標簽均為<none>
,這類無標簽、無倉儲名的鏡像被稱為dangling image
。
拉取推送
# 拉取鏡像
docker pull [imagename]
# 構建鏡像
docker build
# 推送鏡像
docker push [imagename]
其他
# 查看鏡像、容器、卷占用的空間
docker system df
Dockerfile
Dcoker鏡像是從一個基礎鏡像開始的,基礎鏡像包括應用程序所需的平台依賴項, 例如, 安裝了JVM
或CLR
等。
鏡像的定義是使用dockerfile
文件來表達的。dockerfile
是描述如何部署應用的列表。一個簡單的Dockerfile
文件如下:
FROM nginx:alpine
COPY . /usr/share/nginx/html
如上,我們的基礎鏡像是一個alpine版本的nginx
,從而擁有了一個安裝了nginx
的linux環境。
接下來,我們可以通過定義的dockerfile
文件來構建鏡像:
docker build -t webserver-image:v1 .
其-t
參數為鏡像指定一個友好的名字和標記,.
則表示使用當前目錄的dockerfile
文件。
OnBuild
通常,dockerfile
文件的執行順序是從上到下,但我們可以使用ONBUILD
指令來延后執行(在子鏡像構建時執行)。
如下,我們定義一個經典的Node
應用程序基礎鏡像:
FROM node:10
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ONBUILD COPY package.json /usr/src/app/
ONBUILD RUN npm install
ONBUILD COPY . /usr/src/app
CMD [ "npm", "start" ]
當我們構建該鏡像時,ONBUILD
指令包含的內容將不會執行,然后我們定義一個該鏡像的子鏡像:
FROM node:10-onbuild
EXPOSE 3000
當我們構建該鏡像時,上面的ONBUILD
才會被執行。這樣做的優勢是可以在多個鏡像中共享一份基礎鏡像,大大減少構建的速度。
Ignore File
為了防止將一個不必要或者敏感的數據打包到鏡像中,可以使用.dockerignore
文件進行配置。
下面的命令將passwords.txt
文件加到了忽略中,確保它不會意外的被打包到鏡像中發布出去。
echo passwords.txt >> .dockerignore
我們可以將.dockerignore
文件存儲在源代碼管理中,保持團隊間的一致。
總結
Docker是革命性的,干凈利落的UX俘獲了技術人員的芳心,ASP.NET Core 也是全面擁抱Docker,我們也要緊跟時代的步伐。
本文主要介紹docker的一些基本用法,可作為一個docker使用筆記來參考,並不斷的補充完善,但不會涉及到比較深入的介紹,后續在其他文章中會詳細介紹一些具體的用法。