精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何遷移docker的存儲目錄

馬哥Linux運維 ? 來源:奇妙的Linux世界 ? 作者:奇妙的Linux世界 ? 2022-07-03 09:21 ? 次閱讀

1Docker 遷移存儲目錄

默認情況系統會將 Docker 容器存放在 /var/lib/docker 目錄下

[問題起因]今天通過監控系統,發現公司其中一臺服務器的磁盤快慢,隨即上去看了下,發現/var/lib/docker這個目錄特別大。由上述原因,我們都知道,在/var/lib/docker中存儲的都是相關于容器的存儲,所以也不能隨便的將其刪除掉。

那就準備遷移docker的存儲目錄吧,或者對/var設備進行擴容來達到相同的目的。更多關于dockerd的詳細參數,請點擊查看官方文檔地址。

但是需要注意的一點就是,盡量不要用軟鏈, 因為一些docker容器編排系統不支持這樣做,比如我們所熟知的k8s就在內。

#發現容器啟動不了了
ERROR:cannot  create temporary directory!

#查看系統存儲情況
$du-h--max-depth=1

[解決方法 1] 添加軟鏈接

#1.停止docker服務
$sudosystemctlstopdocker

#2.開始遷移目錄
$sudomv/var/lib/docker/data/

#3.添加軟鏈接
$sudoln-s/data/docker/var/lib/docker

#4.啟動docker服務
$sudosystemctlstartdocker

[解決方法 2] 改動 docker 配置文件

#[方式一]改動docker啟動配置文件
$sudovim/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd--graph=/data/docker/
#[方式二]改動docker啟動配置文件
$sudovim/etc/docker/daemon.json
{
"live-restore":true,
"graph":["/data/docker/"]
}

[操作注意事項]在遷移docker目錄的時候注意使用的命令,要么使用mv命令直接移動,要么使用cp命令復制文件,但是需要注意同時復制文件權限和對應屬性,不然在使用的時候可能會存在權限問題。如果容器中,也是使用root用戶,則不會存在該問題,但是也是需要按照正確的操作來遷移目錄。

#使用mv命令
$sudomv/var/lib/docker/data/docker

#使用cp命令
$sudocp-arv/data/docker/data2/docker

下圖中,就是因為啟動的容器使用的是普通用戶運行進程的,且在運行當中需要使用/tmp目錄,結果提示沒有權限。在我們導入容器鏡像的時候,其實是會將容器啟動時需要的各個目錄的權限和屬性都賦予了。如果我們直接是cp命令單純復制文件內容的話,就會出現屬性不一致的情況,同時還會有一定的安全問題。

81b7ead8-fa10-11ec-ba43-dac502259ad0.pngDocker遷移存儲目錄

2Docker 設備空間不足

Increase Docker container size from default 10GB on rhel7.

[問題起因一]容器在導入或者啟動的時候,如果提示磁盤空間不足的,那么多半是真的因為物理磁盤空間真的有問題導致的。如下所示,我們可以看到/分區確實滿了。

#查看物理磁盤空間
$df-Th
FilesystemSizeUsedAvailUse%Mountedon
/dev/vda140G40G0G100%/
tmpfs7.8G07.8G0%/dev/shm
/dev/vdb1493G289G179G62%/mnt

如果發現真的是物理磁盤空間滿了的話,就需要查看到底是什么占據了如此大的空間,導致因為容器沒有空間無法啟動。其中,docker自帶的命令就是一個很好的能夠幫助我們發現問題的工具。

#查看基本信息
#硬件驅動使用的是devicemapper,空間池為docker-252
#磁盤可用容量僅剩16.78MB,可用供我們使用
$dockerinfo
Containers:1
Images:28
StorageDriver:devicemapper
PoolName:docker-252:1-787932-pool
PoolBlocksize:65.54kB
BackingFilesystem:extfs
Datafile:/dev/loop0
Metadatafile:/dev/loop1
DataSpaceUsed:1.225GB
DataSpaceTotal:107.4GB
DataSpaceAvailable:16.78MB
MetadataSpaceUsed:2.073MB
MetadataSpaceTotal:2.147GB

[解決方法]通過查看信息,我們知道正是因為docker可用的磁盤空間不足,所以導致啟動的時候沒有足夠的空間進行加載啟動鏡像。解決的方法也很簡單,第一就是清理無效數據文件釋放磁盤空間(清除日志),第二就是修改docker數據的存放路徑(大分區)。

#顯示哪些容器目錄具有最大的日志文件
$du-d1-h/var/lib/docker/containers|sort-h

#清除您選擇的容器日志文件的內容
$cat/dev/null>/var/lib/docker/containers/container_id/container_log_name

[問題起因二]顯然我遇到的不是上一種情況,而是在啟動容器的時候,容器啟動之后不久就顯示是unhealthy的狀態,通過如下日志發現,原來是復制配置文件啟動的時候,提示磁盤空間不足。

后面發現是因為CentOS7的系統使用的docker容器默認的創建大小就是10G而已,然而我們使用的容器卻超過了這個限制,導致無法啟動時提示空間不足。

2019-08-161115,816INFOspawned:'app-demo'withpid835
2019-08-161116,268INFOexited:app(exitstatus1;notexpected)
2019-08-161117,270INFOgaveup:appenteredFATALstate,toomanystartretriestooquickly
cp:cannotcreateregularfile'/etc/supervisor/conf.d/grpc-app-demo.conf':Nospaceleftondevice
cp:cannotcreateregularfile'/etc/supervisor/conf.d/grpc-app-demo.conf':Nospaceleftondevice
cp:cannotcreateregularfile'/etc/supervisor/conf.d/grpc-app-demo.conf':Nospaceleftondevice
cp:cannotcreateregularfile'/etc/supervisor/conf.d/grpc-app-demo.conf':Nospaceleftondevice

[解決方法 1] 改動 docker 啟動配置文件

#/etc/docker/daemon.json
{
"live-restore":true,
"storage-opt":["dm.basesize=20G"]
}

[解決方法 2] 改動 systemctl 的 docker 啟動文件

#1.stopthedockerservice
$sudosystemctlstopdocker

#2.rmexisedcontainer
$sudorm-rf/var/lib/docker

#2.edityourdockerservicefile
$sudovim/usr/lib/systemd/system/docker.service

#3.findtheexecutionline
ExecStart=/usr/bin/dockerd
andchangeitto:
ExecStart=/usr/bin/dockerd--storage-optdm.basesize=20G

#4.startdockerserviceagain
$sudosystemctlstartdocker

#5.reloaddaemon
$sudosystemctldaemon-reload

[問題起因三]還有一種情況也會讓容器無法啟動,并提示磁盤空間不足,但是使用命令查看發現并不是因為物理磁盤真的不足導致的。而是,因為對于分區的inode節點數滿了導致的。

#報錯信息
Nospaceleftondevice

[解決方法]因為ext3文件系統使用inode table存儲inode信息,而xfs文件系統使用B+ tree來進行存儲。考慮到性能問題,默認情況下這個B+ tree只會使用前1TB空間,當這1TB空間被寫滿后,就會導致無法寫入inode信息,報磁盤空間不足的錯誤。我們可以在mount時,指定inode64即可將這個B+ tree使用的空間擴展到整個文件系統。

Docker+K8s+Jenkins 主流技術全解視頻資料【干貨免費分享】

#查看系統的inode節點使用情況
$sudodf-i

#嘗試重新掛載
$sudomount-oremount-onoatime,nodiratime,inode64,nobarrier/dev/vda1

[補充知識]文件儲存在硬盤上,硬盤的最小存儲單位叫做扇區(Sector)。每個扇區儲存512字節(相當于0.5KB)。操作系統讀取硬盤的時候,不會一個個扇區地讀取,這樣效率太低,而是一次性連續讀取多個扇區,即一次性讀取一個(block)。這種由多個扇區組成的,是文件存取的最小單位。的大小,最常見的是4KB,即連續八個sector組成一個block塊。文件數據都儲存在中,那么很顯然,我們還必須找到一個地方儲存文件的元信息,比如文件的創建者、文件的創建日期、文件的大小等等。這種儲存文件元信息的區域就叫做索引節點(inode)。每一個文件都有對應的inode,里面包含了除了文件名以外的所有文件信息。

inode也會消耗硬盤空間,所以硬盤格式化的時候,操作系統自動將硬盤分成兩個區域。一個是數據區,存放文件數據;另一個是inode區(inode table),存放inode所包含的信息。每個inode節點的大小,一般是128字節或256字節。inode節點的總數,在格式化時就給定,一般是每1KB或每2KB就設置一個inode節點。

#每個節點信息的內容
$statcheck_port_live.sh
File:check_port_live.sh
Size:225Blocks:8IOBlock:4096regularfile
Device:822h/2082dInode:99621663Links:1
Access:(0755/-rwxr-xr-x)Uid:(1006/escape)Gid:(1006/escape)
Access:2019-07-291459.498076903+0800
Modify:2019-07-291459.498076903+0800
Change:2019-07-292327.834866649+0800
Birth:-

#磁盤的inode使用情況
$df-i
FilesystemInodesIUsedIFreeIUse%Mountedon
udev16478355801164775541%/dev
tmpfs164876392521164851181%/run
/dev/sdc224416256047884362393741242%/
tmpfs164876395164876341%/dev/shm

3Docker 缺共享鏈接庫

Docker 命令需要對/tmp 目錄下面有訪問權限

[問題起因]給系統安裝完compose之后,查看版本的時候,提示缺少一個名為libz.so.1的共享鏈接庫。第一反應就是,是不是系統少安裝那個軟件包導致的。隨即,搜索了一下,將相關的依賴包都給安裝了,卻還是提示同樣的問題。

#提示錯誤信息
$docker-compose--version
errorwhileloadingsharedlibraries:libz.so.1:failedtomapsegmentfromsharedobject:Operationnotpermitted

[解決方法]后來發現,是因為系統中docker沒有對/tmp目錄的訪問權限導致,需要重新將其掛載一次,就可以解決了。

#重新掛載
$sudomount/tmp-oremount,exec

4Docker 容器文件損壞

對 dockerd 的配置有可能會影響到系統穩定

[問題起因]容器文件損壞,經常會導致容器無法操作。正常的docker命令已經無法操控這臺容器了,無法關閉、重啟、刪除。正巧,前天就需要這個的問題,主要的原因是因為重新對docker的默認容器進行了重新的分配限制導致的。

#操作容器遇到類似的錯誤
b'devicemapper:ErrorrunningdeviceCreate(CreateSnapDeviceRaw)dm_task_runfailed'

[解決方法]可以通過以下操作將容器刪除/重建。

#1.關閉docker
$sudosystemctlstopdocker

#2.刪除容器文件
$sudorm-rf/var/lib/docker/containers

#3.重新整理容器元數據
$sudothin_check/var/lib/docker/devicemapper/devicemapper/metadata
$sudothin_check--clear-needs-check-flag/var/lib/docker/devicemapper/devicemapper/metadata

#4.重啟docker
$sudosystemctlstartdocker

5Docker 容器優雅重啟

不停止服務器上面運行的容器,重啟 dockerd 服務是多么好的一件事

[問題起因]默認情況下,當Docker守護程序終止時,它會關閉正在運行的容器。從Docker-ce 1.12開始,可以在配置文件中添加live-restore參數,以便在守護程序變得不可用時容器保持運行。需要注意的是Windows平臺暫時還是不支持該參數的配置。

#Keepcontainersaliveduringdaemondowntime
$sudovim/etc/docker/daemon.yaml
{
"live-restore":true
}

#在守護進程停機期間保持容器存活
$sudodockerd--live-restore

#只能使用reload重載
#相當于發送SIGHUP信號量給dockerd守護進程
$sudosystemctlreloaddocker

#但是對應網絡的設置需要restart才能生效
$sudosystemctlrestartdocker

[解決方法]可以通過以下操作將容器刪除/重建。

#/etc/docker/daemon.yaml
{
"registry-mirrors":["https://vec0xydj.mirror.aliyuncs.com"],#配置獲取官方鏡像的倉庫地址
"experimental":true,#啟用實驗功能
"default-runtime":"nvidia",#容器的默認OCI運行時(默認為runc)
"live-restore":true,#重啟dockerd服務的時候容易不終止
"runtimes":{#配置容器運行時
"nvidia":{
"path":"/usr/bin/nvidia-container-runtime",
"runtimeArgs":[]
}
},
"default-address-pools":[#配置容器使用的子網地址池
{
"scope":"local",
"base":"172.17.0.0/12",
"size":24
}
]
}
$vim/etc/docker/daemon.json
{
"default-address-pools":[
{
"base":"172.240.0.0/16",
"size":24
}
]
}

6Docker 容器無法刪除

找不到對應容器進程是最嚇人的

[問題起因]今天遇到docker容器無法停止/終止/刪除,以為這個容器可能又出現了dockerd守護進程托管的情況,但是通過ps -ef 無法查到對應的運行進程。哎,后來開始開始查supervisor以及Dockerfile中的進程,都沒有。這種情況的可能原因是容器啟動之后,主機因任何原因重新啟動并且沒有優雅地終止容器。剩下的文件現在阻止你重新生成舊名稱的新容器,因為系統認為舊容器仍然存在。

#刪除容器
$sudodockerrm-ff8e8c3..
Errorresponsefromdaemon:Conflict,cannotremovethedefaultnameofthecontainer

[解決方法]找到/var/lib/docker/containers/下的對應容器的文件夾,將其刪除,然后重啟一下dockerd即可。我們會發現,之前無法刪除的容器沒有了。

#刪除容器文件
$sudorm-rf/var/lib/docker/containers/f8e8c3...65720

#重啟服務
$sudosystemctlrestartdocker.service

7Docker 容器中文異常

容器存在問題話,記得優先在官網查詢

[問題起因]今天登陸之前部署的MySQL數據庫查詢,發現使用SQL語句無法查詢中文字段,即使直接輸入中文都沒有辦法顯示。

#查看容器支持的字符集
root@b18f56aa1e15:#locale-a
C
C.UTF-8
POSIX

[解決方法]Docker部署的MySQL系統使用的是POSIX字符集。然而POSIX字符集是不支持中文的,而C.UTF-8是支持中文的只要把系統中的環境LANG改為"C.UTF-8"格式即可解決問題。同理,在K8S進入pod不能輸入中文也可用此方法解決。

#臨時解決
dockerexec-itsome-mysqlenvLANG=C.UTF-8/bin/bash
#永久解決
dockerrun--namesome-mysql
-eMYSQL_ROOT_PASSWORD=my-secret-pw
-dmysql:tag--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci

8Docker 容器網絡互通

了解 Docker 的四種網絡模型

[問題起因]在本機部署Nginx容器想代理本機啟動的Python后端服務程序,但是對代碼服務如下的配置,結果訪問的時候一直提示502錯誤。

#啟動Nginx服務
$dockerrun-d-p80:80$PWD:/etc/nginxnginx
server{
...
location/api{
proxy_passhttp://localhost:8080
}
...
}

[解決方法]后面發現是因為nginx.conf配置文件中的localhost配置的有問題,由于Nginx是在容器中運行,所以localhost為容器中的localhost,而非本機的localhost,所以導致無法訪問。

可以將nginx.conf中的localhost改為宿主機的IP地址,就可以解決502的錯誤。

#查詢宿主機IP地址=>172.17.0.1
$ipaddrshowdocker0
docker0:mtu1500qdiscnoqueuestateUPgroupdefault
link/ether02d5f2:1ebrdffffff:ff
inet172.17.0.1/16scopeglobaldocker0
valid_lftforeverpreferred_lftforever
inet6fe80:d5fff21e/64scopelink
valid_lftforeverpreferred_lftforever
server{
...
location/api{
proxy_passhttp://172.17.0.1:8080
}
...
}

當容器使用host網絡時,容器與宿主共用網絡,這樣就能在容器中訪問宿主機網絡,那么容器的localhost就是宿主機的localhost了。

#服務的啟動方式有所改變(沒有映射出來端口)
#因為本身與宿主機共用了網絡,宿主機暴露端口等同于容器中暴露端口
$dockerrun-d-p80:80--network=host$PWD:/etc/nginxnginxx

9Docker 容器總線錯誤

總線錯誤看到的時候還是挺嚇人了

[問題起因]在docker容器中運行程序的時候,提示bus error錯誤。

#總線報錯
$invapp.user_op--name=zhangsan
Buserror(coredumped)

[解決方法]原因是在docker運行的時候,shm分區設置太小導致share memory不夠。不設置--shm-size參數時,docker給容器默認分配的shm大小為64M,導致程序啟動時不足。具體原因還是因為安裝pytorch包導致了,多進程跑任務的時候,docker容器分配的共享內存太小,導致torch要在tmpfs上面放模型數據用于子線程的 共享不足,就出現報錯了。

#問題原因
root@18...35:/opt/app#df-TH
FilesystemTypeSizeUsedAvailUse%Mountedon
overlayoverlay2.0T221G1.4T3%/
tmpfstmpfs68M068M0%/dev
shmtmpfs68M41k68M1%/dev/shm

#啟動docker的時候加上--shm-size參數(單位為b,k,m或g)
$dockerrun-it--rm--shm-size=200mpytorch/pytorch:latest

#在docker-compose添加對應配置
$shm_size:'2gb'

[解決方法]還有一種情況就是容器內的磁盤空間不足,也會導致bus error這樣的報錯,所以如果出現了,清除多余文件和目錄或者分配一個大的磁盤空間,就可以解決了。

#磁盤空間不足
$df-Th
FilesystemTypeSizeUsedAvailUse%Mountedon
overlayoverlay1T1T0G100%/
shmtmpfs64M24K64M1%/dev/shm

10Docker NFS 掛載報錯

NFS 掛載之后容器程序使用異常為內核版本太低導致的

[問題起因]我們將服務部署到openshift集群中,啟動服務調用資源文件的時候,報錯信息如下所示。從報錯信息中,得知是在Python3程序執行read_file()讀取文件的內容,給文件加鎖的時候報錯了。但是奇怪的是,本地調試的時候發現服務都是可以正常運行的,文件加鎖也是沒問題的。后來發現,在openshift集群中使用的是NFS掛載的共享磁盤。

#報錯信息
Traceback(mostrecentcalllast):
......
File"xxx/utils/storage.py",line34,inxxx.utils.storage.LocalStorage.read_file
OSError:[Errno9]Badfiledescriptor
#文件加鎖代碼
...
withopen(self.mount(path),'rb')asfileobj:
fcntl.flock(fileobj,fcntl.LOCK_EX)
data=fileobj.read()
returndata
...

[解決方法]從下面的信息得知,要在Linux中使用flock()的話,就需要升級內核版本到2.6.11+才行。后來才發現,這實際上是由RedHat內核中的一個錯誤引起的,并在kernel-3.10.0-693.18.1.el7版本中得到修復。所以對于NFSv3和NFSv4服務而已,就需要升級Linux內核版本才能夠解決這個問題。

#https://t.codebug.vip/questions-930901.htm
$InLinuxkernelsupto2.6.11,flock()doesnotlockfilesoverNFS(i.e.,
thescopeoflockswaslimitedtothelocalsystem).[...]SinceLinux2.6.12,
NFSclientssupportflock()locksbyemulatingthemasbyte-rangelocksontheentirefile.

11Docker 使用默認網段

啟動的容器網絡無法相互通信,很是奇怪!

[問題起因]我們在使用Docker啟動服務的時候,發現有時候服務之前可以相互連通,而有時啟動的多個服務之前卻出現了無法訪問的情況。究其原因,發現原來是因為使用的內部私有地址網段不一致導致的。有的服務啟動到了172.17 - 172.31的網段,有的服務跑到了192.169.0 - 192.168.224的網段,這樣導致服務啟動之后出現無法訪問的情況(默認情況下,有下面這個兩個網段可供其使用)。

81cd617e-fa10-11ec-ba43-dac502259ad0.pngDocker默認使用網段

[解決方法]上述問題的處理方式,就是手動指定Docker服務的啟動網段,二選一就可以了。

#查看docker容器配置
$cat/etc/docker/daemon.json
{
"registry-mirrors":["https://vec0xydj.mirror.aliyuncs.com"],
"default-address-pools":[{"base":"172.17.0.0/12","size":24}],
"experimental":true,
"default-runtime":"nvidia",
"live-restore":true,
"runtimes":{
"nvidia":{
"path":"/usr/bin/nvidia-container-runtime",
"runtimeArgs":[]
}
}
}

12Docker 服務啟動串臺

使用 docker-compose 命令各自啟動兩組服務,發現服務會串臺!

[問題起因]在兩個不同名稱的目錄目錄下面,使用docker-compose來啟動服務,發現當A組服務啟動完畢之后,再啟動B組服務的時候,發現A組當中對應的一部分服務又重新啟動了一次,這就非常奇怪了!因為這個問題的存在會導致,A組服務和B組服務無法同時啟動。之前還以為是工具的Bug,后來請教了“上峰”,才知道了原因,恍然大悟。

#服務目錄結構如下所示
A:/data1/app/docker-compose.yml
B:/data2/app/docker-compose.yml

[解決方法]發現A和B兩組服務會串臺的原因,原來是docker-compose會給啟動的容器加label標簽,然后根據這些label標簽來識別和判斷對應的容器服務是由誰啟動的、誰來管理的,等等。而這里,我們需要關注的label變量是com.docker.compose.project,其對應的值是使用啟動配置文件的目錄的最底層子目錄名稱,即上面的app就是對應的值。我們可以發現,A和B兩組服務對應的值都是app,所以啟動的時候被認為是同一個,這就出現了上述的問題。如果需要深入了解的話,可以去看對應源代碼。

81e53628-fa10-11ec-ba43-dac502259ad0.pngDocker服務啟動串臺

#可以將目錄結構調整為如下所示
A:/data/app1/docker-compose.yml
B:/data/app2/docker-compose.yml

A:/data1/app-old/docker-compose.yml
B:/data2/app-new/docker-compose.yml

或者使用docker-compose命令提供的參數-p手動指定標簽,來規避該問題的發生。

#指定項目項目名稱
$docker-compose-f./docker-compose.yml-papp1up-d

13Docker 命令調用報錯

在編寫腳本的時候常常會執行 docker 相關的命令,但是需要注意使用細節!

[問題起因]CI更新環境執行了一個腳本,但是腳本執行過程中報錯了,如下所示。通過對應的輸出信息,可以看到提示說正在執行的設備不是一個tty。

81f38048-fa10-11ec-ba43-dac502259ad0.pngDocker命令調用報錯

隨即,查看了腳本發現報錯地方是執行了一個exec的docker命令,大致如下所示。很奇怪的是,手動執行或直接調腳本的時候,怎么都是沒有問題的,但是等到CI調用的時候怎么都是有問題。后來好好看下,下面這個命令,注意到-it這個參數了。

#腳本調用docker命令
dockerexec-itpsql-Upostgres......

我們可以一起看下exec命令的這兩個參數,自然就差不多理解了。

編號 參數 解釋說明
1 -i/-interactive 即使沒有附加也保持 STDIN 打開;如果你需要執行命令則需要開啟這個選項
2 -t/–tty 分配一個偽終端進行執行;一個連接用戶的終端與容器 stdin 和 stdout 的橋梁

[解決方法]docker exec的參數-t是指Allocate a pseudo-TTY的意思,而CI在執行job的時候并不是在TTY終端中執行,所以-t這個參數會報錯。同時在 『stackoverflow』也有人給出原因,可以自行查看。

8215fcae-fa10-11ec-ba43-dac502259ad0.pngDocker命令調用報錯

14Docker 定時任務異常

在 Crontab 定時任務中也存在 Docker 命令執行異常的情況!

[問題起因]今天發現了一個問題,就是在備份Mysql數據庫的時候,使用docker容器進行備份,然后使用Crontab定時任務來觸發備份。但是發現備份的MySQL數據庫居然是空的,但是手動執行對應命令切是好的,很奇怪。

#Crontab定時任務
0*/6***
dockerexec-itsh-c
'execmysqldump--all-databases-uroot-ppassword......'

[解決方法]后來發現是因為執行的docker命令多個-i導致的。因為Crontab命令執行的時候,并不是交互式的,所以需要把這個去掉才可以。總結就是,如果你需要回顯的話則需要-t選項,如果需要交互式會話則需要-i選項。

編號 參數 解釋說明
1 -i/-interactive 即使沒有附加也保持 STDIN 打開;如果你需要執行命令則需要開啟這個選項
2 -t/–tty 分配一個偽終端進行執行;一個連接用戶的終端與容器 stdin 和 stdout 的橋梁

15Docker 變量使用引號

compose 里邊環境變量帶不帶引號的問題!

[問題起因]使用過compose的朋友可能都遇到過,在編寫啟服務啟動配置文件的時候,添加環境變量時到底是使用單引號、雙引號還是不使用引號的問題?時間長了,我們可能會將三者混用,認為其效果是一樣的。但是后來,發現的坑越來越多,才發現其越來越隱晦。

反正我是遇到過很多問題,都是因為添加引號導致的服務啟動異常的,后來得出的結論就是一律不使引號。裸奔,體驗前所未有的爽快!直到現在看到了Github中對應的 issus 之后,才終于破案了。

#在Compose中進行引用TEST_VAR變量,無法找到
TEST_VAR="test"

#在Compose中進行引用TEST_VAR變量,可以找到
TEST_VAR=test

#后來發現docker本身其實已經正確地處理了引號的使用
dockerrun-it--rm-eTEST_VAR="test"test:latest

[解決方法]得到的結論就是,因為Compose解析yaml配置文件,發現引號也進行了解釋包裝。這就導致原本的TEST_VAR="test"被解析成了'TEST_VAR="test"',所以我們在引用的時候就無法獲取到對應的值。現在解決方法就是,不管是我們直接在配置文件添加環境變量或者使用env_file配置文件,能不使用引號就不適用引號。

需要注意的是環境變量配置的是日志格式的話(2022-01-01),如果使用的是Python的yaml.load模塊的話,會被當做是date類型的,這是如果希望保持原樣信息的話,可以使用'/"引起來將其變成字符串格式的。

16Docker 刪除鏡像報錯

無法刪除鏡像,歸根到底還是有地方用到了!

[問題起因]清理服器磁盤空間的時候,刪除某個鏡像的時候提示如下信息。提示需要強制刪除,但是發現及時執行了強制刪除依舊沒有效果。

#刪除鏡像
$dockerrmi3ccxxxx2e862
Errorresponsefromdaemon:conflict:unabletodelete3ccxxxx2e862(cannotbeforced)-imagehasdependentchildimages

#強制刪除
$dcokerrmi-f3ccxxxx2e862
Errorresponsefromdaemon:conflict:unabletodelete3ccxxxx2e862(cannotbeforced)-imagehasdependentchildimages

[解決方法]后來才發現,出現這個原因主要是因為TAG,即存在其他鏡像引用了這個鏡像。這里我們可以使用如下命令查看對應鏡像文件的依賴關系,然后根據對應TAG來刪除鏡像。

#查詢依賴-image_id表示鏡像名稱
$dockerimageinspect--format='{{.RepoTags}}{{.Id}}{{.Parent}}'$(dockerimagels-q--filtersince=)

#根據TAG刪除鏡像
$dockerrmi-fc565xxxxc87f
#刪除懸空鏡像
$dockerrmi$(dockerimages--filter"dangling=true"-q--no-trunc)

17Docker 普通用戶切換

切換 Docker 啟動用戶的話,還是需要注意下權限問題的!

[問題起因]我們知道在Docker容器里面使用root用戶的話,是不安全的,很容易出現越權的安全問題,所以一般情況下,我們都會使用普通用戶來代替root進行服務的啟動和管理的。今天給一個服務切換用戶的時候,發現Nginx服務一直無法啟動,提示如下權限問題。因為對應的配置文件也沒有配置var相關的目錄,無奈 ? !

#Nginx報錯信息
nginx:[alert]couldnotopenerrorlogfile:open()"/var/log/nginx/error.log"failed(13:Permissiondenied)
2020/11/121547[emerg]23#23:mkdir()"/var/cache/nginx/client_temp"failed(13:Permissiondenied)

[解決方法]后來發現還是nginx.conf配置文件,配置的有問題,需要將Nginx服務啟動時候需要的文件都配置到一個無權限的目錄,即可解決。

userwww-data;
worker_processes1;

error_log/data/logs/master_error.logwarn;
pid/dev/shm/nginx.pid;

events{
worker_connections1024;
}

http{
include/etc/nginx/mime.types;
default_typeapplication/octet-stream;

gzipon;
sendfileon;
tcp_nopushon;
keepalive_timeout65;

client_body_temp_path/tmp/client_body;
fastcgi_temp_path/tmp/fastcgi_temp;
proxy_temp_path/tmp/proxy_temp;
scgi_temp_path/tmp/scgi_temp;
uwsgi_temp_path/tmp/uwsgi_temp;

include/etc/nginx/conf.d/*.conf;
}

18Docker 綁定到 IPv6 上

Docker 服務在啟動的時候,將地址綁定到 IPv6 地址上面了,提示報錯信息!

[問題起因]物理機器更新了對應補丁之后,重啟了服務,導致原本可以正常啟動的docker-compose服務提示如下報錯信息。不清楚是否修改了操作系統的相關配置,還是對應docker進行的其他方面的配置,比如修改/etc/docker/daemon.json或者docker的service啟動文件。

#Docker的報錯信息
dockerrun-p80:80nginx:alpinesucceeds.Previously,thiswasfailingwithError
startinguserlandproxy:listentcp6[::]socket:addressfamilynotsupportedbyprotocol.

[解決方法]通過如上所示的報錯信息,可以看到服務的啟動端口綁定到了tcp6上面了,但是對應的socket發現系統本身并不支持。這時,我們一看下對應的操作系統ipv6的設置,發現系統禁用了,所有的ipv6地址。需要了解的朋友,可以參考 fix port forwarding with ipv6.disable=1 和 cannot start if ipv6 is disabled on host 這兩個issus來獲取更多信息。

#操作系統配置
$cat/etc/sysctl.conf|grepipv6
net.ipv6.conf.all.disable_ipv6=1

[方法一]最為簡單的解決方法,就是在docker-compose.yml文件中,手動指定將對應服務的端口綁定到ipv4上面,如下所示。

version:"3"

services:
app:
restart:on-failure
container_name:app_web
image:app:latest
ports:
-"0.0.0.080/tcp"
volumes:
-"./app_web:/data"
networks:
-app_network

networks:
app_network:

[方法二]或者修改/etc/docker/daemon.json文件,在配置中,阻止Docker錯誤的將端口映射到IPv6上,即可達到同樣的效果,且不用再次修改多個服務的啟動配置文件了。

#修改配置
$vim/etc/docker/daemon.json
{
"ipv6":false,
"fixed-cidr-v6":"20011::/64"
}

#重啟服務
$systemctlreloaddocker

[方法三]Docker默認情況下會同時將端口映射于IPv4與IPv6兩者上,而且有的時候會出現只綁定到了IPv6,導致服務無法正常訪問的情況。現在通用的始終還是IPv4地址,因此最簡單的做法就是關閉IPv6地址。詳細的配置,可以參考 Port redirecting binding to IPv6 but not IPv4 interfaces 這個issus地址。

#修改系統配置
echo'1'>/proc/sys/net/ipv6/conf/lo/disable_ipv6
echo'1'>/proc/sys/net/ipv6/conf/lo/disable_ipv6
echo'1'>/proc/sys/net/ipv6/conf/all/disable_ipv6
echo'1'>/proc/sys/net/ipv6/conf/default/disable_ipv6

#重啟網絡
$/etc/init.d/networkingrestart

#最后檢測是否已關閉IPv6
ipaddrshow|grepnet6

1919. Docker 容器啟動超時

Docker 服務在啟動的時候,提示超時,被直接終止了!

[問題起因]使用docker-compose啟動容器的時候,等待了很久的時候(大約2-3分鐘左右),之后提示如下信息。通過閱讀信息內容,可以看到是因為超時導致的,提示可以通過設置環境變量,加大超時的時間。

$docker-composeup-d
ERROR:forxxxUnixHTTPConnectionPool(host='localhost',port=None):Readtimedout.(readtimeout=70)
ERROR:AnHTTPrequesttooktoolongtocomplete.Retrywith--verbosetoobtaindebuginformation.
Ifyouencounterthisissueregularlybecauseofslownetworkconditions,considersettingCOMPOSE_HTTP_TIMEOUTtoahighervalue(currentvalue:60).

[解決方法]按照提示設置的環境變量之后,再次啟動發現確實可以正常啟動了,但是還是能夠感覺到有些慢。

$sudovim/etc/profile
exportCOMPOSE_HTTP_TIMEOUT=500
exportDOCKER_CLIENT_TIMEOUT=500

排除了下啟動流程,因為容器啟動有映射目錄到容器里面且目錄大小比較大,所以懷疑是因為i/o導致的。隨即使用iotop命令查看服務器目前的i/o情況,發現存在很多個rg命令,且都處于100%左右。查了下,發現是vscode遠程服務器啟動的搜索目錄結構的進程,西八,有些坑呀!

$sudoiotop
4269be/4escape15.64K/s0.00B/s0.00%98.36%rg--files--hidden
4270be/4escape28.15K/s0.00B/s0.00%97.46%rg--files--hidden
4272be/4escape31.27K/s0.00B/s0.00%97.39%rg--files--hidden
4276be/4escape34.40K/s0.00B/s0.00%96.98%rg--files--hidden

20Docker 端口網絡限制

如果發現服務都一切正常,但是無法無法訪問的話,則多為網絡問題!

[問題起因]啟用服務之后,登錄跳轉發現直接502報錯了。排除了配置等相關原因都沒有任何問題(做過相關測試),這就非常奇怪了!

#部署服務架構
nginx(80)->web1(8080)
->web2(8081)

#報錯信息如下所示
nginxconnect()failed(113:Noroutetohost)whileconnectingtoupstream

[解決方法]根據錯誤信息可知,是因為沒有路由到指定的host導致了,隨即看了下防火墻是開著的,看了日志發現被過濾掉了,西八!問題找到了,現在需要做的就是,要么添加防火墻規則,要么關閉防火墻。

#檢查開放的端口
$sudofirewall-cmd--permanent--zone=public--list-ports

#開啟需要路由的端口
$sudofirewall-cmd--permanent--zone=public--add-port=8080/tcp
$sudofirewall-cmd--permanent--zone=public--add-port=8081/tcp

#配置立即生效
firewall-cmd--reload
#關閉防火墻
$sudosystemctlstopfirewalld.service

#禁用自啟動
$sudosystemctldisablefirewalld.service

21Docker 無法獲取鏡像

新初始化的機器,無法獲取私有倉庫的鏡像文件!

[問題起因]機器初始化之后,使用如下命令登錄私有docker倉庫,發現提示無法獲取對應鏡像,但是在其他機器上面獲取該鏡像就可以執行成功,這就非常奇怪了!

#登錄私有倉庫
$echo'123456'|dockerlogin-uescape--password-stdindocker.escapelife.site

#異常信息提示
$sudodockerpulldocker.escapelife.site/app:0.10
Errorresponsefromdaemon:manifestfordocker.escapelife.site/app:0.10notfound:manifestunknown:manifestunknown

[解決方法]太坑了,我還以為我發現某個隱藏的bug了,可勁的排查,最后發現,原來是自己鏡像包名字寫錯了,應該寫成0.0.10的,自己卻寫成了0.10。這里,紀念一下,以后碰到上述報錯,那肯定是鏡像不存在的。

#登錄私有倉庫之后會在用戶家目錄下生成一個docker配置
#其用來記錄docker私有倉庫的登錄認證信息(是加密過的信息但不安全)=>base64
$cat.docker/config.json
{
"auths":{
"docker.escapelife.site":{
"auth":"d00u11Fu22B3355VG2xasE12w=="
}
}
}

22Docker 使容器不退出

如何使使用 docker-compose 啟動的容器服務 hang 住而不退出

[問題起因]有時候我們啟動的服務,因為某些問題(bug)導致服務無法正常啟動,就會出現容器無限重啟(restart: on-failure)的情況,這時就很不利于排除問題。

?dockerps-a
4e6xxx9a4app:latest"/xxx/…"26secondsagoRestarting(1)2secondsago

[解決方法]這時我們就需要根據,服務構建使用命令來決定是用什么命令來hang住服務。卡住的原理,就類似于使用/bin/bash進入容器是一樣的,這里我就不過多解釋了。

#類似原理
dockerrun-it--rm--entrypoint=/bin/bashxxx/app:latest

#使用Command命令
tty:true
command:tail-f/dev/null

#使用Entrypoint命令
tty:true
entrypoint:tail-f/dev/null

同理,我們在使用docker-compose或者k8s平臺部署服務的時候,也有時會因為啟動問題需要,使啟動的服務不直接退出,來手動調試和排查問題原因。所以,我這里記錄下其不同部署方式的,暫停方式。

#Compose

version:"3"
services:
app:
image:ubuntu:latest
tty:true
entrypoint:/usr/bin/tail
command:"-f/dev/null"
#K8S

apiVersion:v1
kind:Pod
metadata:
name:ubuntu
spec:
containers:
-name:ubuntu
image:ubuntu:latest
command:["/bin/bash","-c","--"]
args:["whiletrue;dosleep30;done;"]
#command:["sleep"]
#args:["infinity"]

23Docker 不使用默認網段

有些情況,內部規劃的網段和可能和 Dockerd 默認的網段有沖突,導致異常出現!

[問題起因]今天在新機器上面,部署了一整套服務(多臺機器),服務部署完畢之后,通過前置Nginx服務發現并不能訪問,后置機器開放的端口,發現發到對應端口的請求都沒有轉發出去。這就比較奇怪了,因為端口控制是已經開通了的,不應該出現不通的情況。

?nc-v172.16.100.128000
nc:connectto172.16.100.12port8000(tcp)failed:Connectionrefused

[解決方法]發現服務器端口不通,我這里懷疑可能是dockerd服務啟動導致的,所以我先將服務都停掉,直接在機器上面啟動了Python的服務端程序(Linux機器自帶Python2.7.x的版本),然后在前置Nginx服務發現,端口確實是通的。后來,排除發現是內部服務默認網段和dockerd服務啟動的默認網段是沖突的,導致重寫了機器的防火墻規則,導致出現上述異常的。

$python-mSimpleHTTPServer8000
ServingHTTPon0.0.0.0port8000...

?nc-v172.16.100.128000
Connectionto172.16.100.128000port[tcp/*]succeeded!

既然問題已經知道了,現在需要做的就是非常簡單了:不適用默認網段!通過 『mirantis』 里面,我們可以選擇進行設置,然后重啟服務dockerd服務,即可。

#修改配置
$sudocat/etc/docker/daemon.json
{
"default-address-pools":[{"base":"192.168.100.0/20","size":24}]
}

#重啟服務
$sudosystemctlrestartdocker

#啟動服務驗證是否生效
$ipa
$dockernetworkinspectapp|grepSubnet
8240047c-fa10-11ec-ba43-dac502259ad0.png

這時,就到了考驗我們網絡的子網劃分的能力了:如何在給定的網段下面合理且高效的進行劃分呢?咳咳,確實難倒我了,這時我們可以再這個在線網站上面 JSON 在線解析 進行劃分,然后選定合理的base和size就可以了。

#報錯信息
Errorresponsefromdaemon:couldnotfindanavailable,non-overlappingIPv4addresspoolamongthedefaultstoassigntothenetwork

#按照下圖我們可以對pool進行合理劃分
#給定10.210.200.0+255.255.255.0的網段來劃分子網
$sudocat/etc/docker/daemon.json
{
"default-address-pools":[{"base":"10.210.200.0/24","size":28}]
}

其中,base告訴我們劃分子網的網段是什么(從來開始),是從前兩位(/16)開始,還是第三位開始(/24)呢?而size則告訴我們劃分的每個子網有多少IP地址可以使用呢?從"10.210.200.0/24"我們可以知道,該網絡下面只有254個可用的IP地址(直接使用肯定不夠),然后我們需要給docker使用,劃分每個子網可用16個IP地址,所以子網就應該寫成28了。

8275d610-fa10-11ec-ba43-dac502259ad0.png Docker 不使用默認網段

24Docker 添加私有倉庫

有些情況,我們服務器上面需要使用內部私有的容器鏡像地址!

[問題起因]如果新機器上面需要使用私有倉庫的話,但是又沒有配置,再獲取鏡像的時候就會出現如下報錯信息。

#拉取/登陸私庫時提示
$dockerpull192.168.31.191:5000/nginx:latest
x509:certificatesignedbyunknownauthority

[解決方法]該問題的處理方式很簡單,如下所示,配置一下倉庫地址,重啟服務并登陸私有倉庫就可以了。

#添加配置
$sudocat/etc/docker/daemon.json
{
"insecure-registries":["192.168.31.191:5000"]
}

#重啟docker
$sudosystemctlrestartdocker

#重新登錄即可
$dockerlogin私庫地址-u用戶名-p密碼

原文標題:24 個 Docker 常見問題處理技巧

文章出處:【微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

審核編輯:彭靜

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲
    +關注

    關注

    13

    文章

    4261

    瀏覽量

    85669
  • 服務器
    +關注

    關注

    12

    文章

    9017

    瀏覽量

    85182
  • Docker
    +關注

    關注

    0

    文章

    454

    瀏覽量

    11814

原文標題:24 個 Docker 常見問題處理技巧

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    ARM平臺實現Docker容器技術

    或網絡接口進行通信。圖1(2)Docker的作用更高效的利用系統資源:Docker對系統資源的利用率更高,無論是應用執行速度,內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。因此,相比虛擬機技術
    發表于 07-17 11:05

    ARM平臺實現Docker容器技術

    或網絡接口進行通信。 圖1(2)Docker的作用更高效的利用系統資源:Docker對系統資源的利用率更高,無論是應用執行速度,內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。因此,相比虛擬機
    發表于 07-25 14:36

    NAS網絡存儲陣列擴容遷移的說明

    1陣列擴容,是只在不改變陣列模式的情況下增加硬盤數量;陣列擴容:打開控制面板----磁盤陣列---選中存儲空間—點擊編輯。 這里可以選擇,選中已經有的磁盤陣列,點擊為陣列增加硬盤。 2陣列遷移
    發表于 09-14 15:54

    Docker數據存儲方式Volumes詳解

    Docker數據存儲之Volumes
    發表于 03-26 11:27

    Docker持久化數據存儲方案

    Docker持久化存儲與數據共享
    發表于 03-23 11:17

    在代碼目錄docker run 時,ls沒有看到代碼是怎么回事?

    在代碼目錄docker run 時,ls沒有看到代碼是怎么回事?如圖
    發表于 01-29 00:10

    嵌入式系統安裝docker的步驟

    系列文章目錄docker 門外初體驗–嵌入式系統安裝docker(九)文章目錄系列文章目錄前言一、設計思路二、操作要點三、驗證四、總結前言嵌
    發表于 12-22 06:27

    docker基礎知識和使用bmnnsdk時的docker常用命令

    安裝docker并下載bmnnsdk2 解壓bmnnsdk壓縮包(以下簡成bmnnsdk為SDK) 進入SDK解壓后文件夾,文件名如bmnnsdk2_bm1684_vx.x.x ,此為宿主機根目錄; 從
    發表于 09-18 07:59

    淺析Docker鏡像本地存儲機制及容器啟動原理

    鏡像各層內容及對應大小,每層對應著 Dockerfile 中的一條指令。Docker 鏡像默認存儲在 /var/lib/docker/《storage-driver》中,可通過 DOCKER
    發表于 10-19 14:17 ?2510次閱讀

    基于Docker的云資源彈性調度策略

    針對云資源彈性調度問題,結合Ceph數據存儲的特點,提出一種基于Docker容器的云資源彈性調度策略。首先,指出Docker容器數據卷不能跨主機的特性給應用在線遷移帶來了困難,并對Ce
    發表于 03-29 10:11 ?0次下載
    基于<b class='flag-5'>Docker</b>的云資源彈性調度策略

    Docker五種存儲驅動原理詳解

    問題,在Docker 0.7版本中引入了存儲驅動, 目前,Docker支持AUFS、Btrfs、Device mapper、OverlayFS、ZFS五種存儲驅動。
    發表于 05-13 10:33 ?2689次閱讀
    <b class='flag-5'>Docker</b>五種<b class='flag-5'>存儲</b>驅動原理詳解

    docker存儲驅動的工作原理

    Docker存儲驅動官方有介紹其工作原理,這里只是簡單概括一下。Docker使用了層的概念,docker在構建鏡像的時候,會逐行執行我們的Dockerfile中的每一行,每執行一行的
    的頭像 發表于 06-26 11:49 ?4553次閱讀

    異構容器云應用遷移系統研究綜述

    為滿足基于 Docker容器的應用在 Kubernetes集群和 Docker swarm集群之間的遷移需求,研究 A-migrator異構容器云應用遷移系統。通過 Kubernete
    發表于 06-09 14:15 ?8次下載

    如何把Docker Registry遷移到Harbor

    “要如何將 docker registry 中的鏡像遷移至 harbor?本文介紹了四種具體的思路和想法供大家參考。 Registry Docker Distribution Docker
    的頭像 發表于 09-07 16:29 ?1502次閱讀
    如何把<b class='flag-5'>Docker</b> Registry<b class='flag-5'>遷移</b>到Harbor

    Docker使用手冊 嵌入式Linux環境搭建

    Desktop”圖標運行,如果一切正常,可以在任務欄看到以下圖標:如果上圖中的鯨魚圖標一直在噴水,表示它還在啟動中。啟動完畢后,鯨魚圖標就不再噴水,你就可以使用Docker了。2.3.3.2 設置Docker存儲
    發表于 11-01 16:32 ?9次下載
    <b class='flag-5'>Docker</b>使用手冊 嵌入式Linux環境搭建