<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          徹夜怒肝!17 個(gè) Docker 常見疑難雜癥解決方案匯總!

          共 24619字,需瀏覽 50分鐘

           ·

          2021-04-06 17:55

          公眾號(hào)關(guān)注“杰哥的IT之旅”,

          選擇“星標(biāo)”,重磅干貨,第一時(shí)間送達(dá)!


          這里主要是為了記錄在使用 Docker 的時(shí)候遇到的問題及其處理解決方法。

          Docker疑難雜癥匯總

          Docker疑難雜癥匯總

          1. Docker 遷移存儲(chǔ)目錄

          默認(rèn)情況系統(tǒng)會(huì)將 Docker 容器存放在/var/lib/docker 目錄下

          [問題起因] 今天通過監(jiān)控系統(tǒng),發(fā)現(xiàn)公司其中一臺(tái)服務(wù)器的磁盤快慢,隨即上去看了下,發(fā)現(xiàn) /var/lib/docker 這個(gè)目錄特別大。由上述原因,我們都知道,在 /var/lib/docker 中存儲(chǔ)的都是相關(guān)于容器的存儲(chǔ),所以也不能隨便的將其刪除掉。

          那就準(zhǔn)備遷移 docker 的存儲(chǔ)目錄吧,或者對(duì) /var 設(shè)備進(jìn)行擴(kuò)容來達(dá)到相同的目的。更多關(guān)于 dockerd 的詳細(xì)參數(shù)。

          但是需要注意的一點(diǎn)就是,盡量不要用軟鏈, 因?yàn)橐恍?docker 容器編排系統(tǒng)不支持這樣做,比如我們所熟知的 k8s 就在內(nèi)。

          # 發(fā)現(xiàn)容器啟動(dòng)不了了
          ERROR:cannot  create temporary directory!

          # 查看系統(tǒng)存儲(chǔ)情況
          $ du -h --max-depth=1

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

          # 1.停止docker服務(wù)
          $ sudo systemctl stop docker

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

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

          # 4.啟動(dòng)docker服務(wù)
          $ sudo systemctl start docker

          [解決方法 2] 改動(dòng) docker 配置文件

          # 3.改動(dòng)docker啟動(dòng)配置文件
          $ sudo vim /lib/systemd/system/docker.service
          ExecStart=/usr/bin/dockerd --graph=/data/docker/
          # 3.改動(dòng)docker啟動(dòng)配置文件
          $ sudo vim /etc/docker/daemon.json
          {
              "live-restore"true,
              "graph": [ "/data/docker/" ]
          }

          [操作注意事項(xiàng)] 在遷移 docker 目錄的時(shí)候注意使用的命令,要么使用 mv 命令直接移動(dòng),要么使用 cp 命令復(fù)制文件,但是需要注意同時(shí)復(fù)制文件權(quán)限和對(duì)應(yīng)屬性,不然在使用的時(shí)候可能會(huì)存在權(quán)限問題。如果容器中,也是使用 root 用戶,則不會(huì)存在該問題,但是也是需要按照正確的操作來遷移目錄。

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

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

          下圖中,就是因?yàn)閱?dòng)的容器使用的是普通用戶運(yùn)行進(jìn)程的,且在運(yùn)行當(dāng)中需要使用 /tmp 目錄,結(jié)果提示沒有權(quán)限。在我們導(dǎo)入容器鏡像的時(shí)候,其實(shí)是會(huì)將容器啟動(dòng)時(shí)需要的各個(gè)目錄的權(quán)限和屬性都賦予了。如果我們直接是 cp 命令單純復(fù)制文件內(nèi)容的話,就會(huì)出現(xiàn)屬性不一致的情況,同時(shí)還會(huì)有一定的安全問題。

          Docker遷移存儲(chǔ)目錄

          2. Docker 設(shè)備空間不足

          Increase Docker container size from default 10GB on rhel7.

          [問題起因一] 容器在導(dǎo)入或者啟動(dòng)的時(shí)候,如果提示磁盤空間不足的,那么多半是真的因?yàn)槲锢泶疟P空間真的有問題導(dǎo)致的。如下所示,我們可以看到 / 分區(qū)確實(shí)滿了。

          # 查看物理磁盤空間
          $ df -Th
          Filesystem    Size    Used    Avail    Use%    Mounted on
          /dev/vda1      40G     40G       0G    100%    /
          tmpfs         7.8G       0     7.8G      0%    /dev/shm
          /dev/vdb1     493G    289G     179G     62%    /mnt

          如果發(fā)現(xiàn)真的是物理磁盤空間滿了的話,就需要查看到底是什么占據(jù)了如此大的空間,導(dǎo)致因?yàn)槿萜鳑]有空間無法啟動(dòng)。其中,docker 自帶的命令就是一個(gè)很好的能夠幫助我們發(fā)現(xiàn)問題的工具。

          # 查看基本信息
          # 硬件驅(qū)動(dòng)使用的是devicemapper,空間池為docker-252
          # 磁盤可用容量?jī)H剩16.78MB,可用供我們使用
          $ docker info
          Containers: 1
          Images: 28
          Storage Driver: devicemapper
           Pool Name: docker-252:1-787932-pool
           Pool Blocksize: 65.54 kB
           Backing Filesystem: extfs
           Data file: /dev/loop0
           Metadata file: /dev/loop1
           Data Space Used: 1.225 GB
           Data Space Total: 107.4 GB
           Data Space Available: 16.78 MB
           Metadata Space Used: 2.073 MB
           Metadata Space Total: 2.147 GB

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

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

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

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

          后面發(fā)現(xiàn)是因?yàn)?CentOS7 的系統(tǒng)使用的 docker 容器默認(rèn)的創(chuàng)建大小就是 10G 而已,然而我們使用的容器卻超過了這個(gè)限制,導(dǎo)致無法啟動(dòng)時(shí)提示空間不足。

          2019-08-16 11:11:15,816 INFO spawned: 'app-demo' with pid 835
          2019-08-16 11:11:16,268 INFO exited: app (exit status 1; not expected)
          2019-08-16 11:11:17,270 INFO gave up: app entered FATAL state, too many start retries too quickly
          cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf'No space left on device
          cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf'No space left on device
          cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf'No space left on device
          cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf'No space left on device

          [解決方法 1] 改動(dòng) docker 啟動(dòng)配置文件

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

          [解決方法 2] 改動(dòng) systemctl 的 docker 啟動(dòng)文件

          # 1.stop the docker service
          $ sudo systemctl stop docker

          # 2.rm exised container
          $ sudo rm -rf /var/lib/docker

          # 2.edit your docker service file
          $ sudo vim /usr/lib/systemd/system/docker.service

          # 3.find the execution line
          ExecStart=/usr/bin/dockerd
          and change it to:
          ExecStart=/usr/bin/dockerd --storage-opt dm.basesize=20G

          # 4.start docker service again
          $ sudo systemctl start docker

          # 5.reload daemon
          $ sudo systemctl daemon-reload

          [問題起因三]還有一種情況也會(huì)讓容器無法啟動(dòng),并提示磁盤空間不足,但是使用命令查看發(fā)現(xiàn)并不是因?yàn)槲锢泶疟P真的不足導(dǎo)致的。而是,因?yàn)閷?duì)于分區(qū)的 inode 節(jié)點(diǎn)數(shù)滿了導(dǎo)致的。

          # 報(bào)錯(cuò)信息
          No space left on device

          [解決方法]因?yàn)?ext3 文件系統(tǒng)使用 inode table 存儲(chǔ) inode 信息,而 xfs 文件系統(tǒng)使用 B+ tree 來進(jìn)行存儲(chǔ)。考慮到性能問題,默認(rèn)情況下這個(gè) B+ tree 只會(huì)使用前 1TB 空間,當(dāng)這 1TB 空間被寫滿后,就會(huì)導(dǎo)致無法寫入 inode 信息,報(bào)磁盤空間不足的錯(cuò)誤。我們可以在 mount 時(shí),指定 inode64 即可將這個(gè) B+ tree 使用的空間擴(kuò)展到整個(gè)文件系統(tǒng)。

          # 查看系統(tǒng)的inode節(jié)點(diǎn)使用情況
          $ sudo df -i

          # 嘗試重新掛載
          $ sudo mount -o remount -o noatime,nodiratime,inode64,nobarrier /dev/vda1

          [補(bǔ)充知識(shí)]文件儲(chǔ)存在硬盤上,硬盤的最小存儲(chǔ)單位叫做“扇區(qū)”(Sector)。每個(gè)扇區(qū)儲(chǔ)存 512 字節(jié)(相當(dāng)于0.5KB)。操作系統(tǒng)讀取硬盤的時(shí)候,不會(huì)一個(gè)個(gè)扇區(qū)地讀取,這樣效率太低,而是一次性連續(xù)讀取多個(gè)扇區(qū),即一次性讀取一個(gè)“塊”(block)。這種由多個(gè)扇區(qū)組成的”塊”,是文件存取的最小單位?!眽K”的大小,最常見的是4KB,即連續(xù)八個(gè) sector 組成一個(gè) block 塊。文件數(shù)據(jù)都儲(chǔ)存在”塊”中,那么很顯然,我們還必須找到一個(gè)地方儲(chǔ)存文件的元信息,比如文件的創(chuàng)建者、文件的創(chuàng)建日期、文件的大小等等。這種儲(chǔ)存文件元信息的區(qū)域就叫做“索引節(jié)點(diǎn)”(inode)。每一個(gè)文件都有對(duì)應(yīng)的 inode,里面包含了除了文件名以外的所有文件信息。

          inode 也會(huì)消耗硬盤空間,所以硬盤格式化的時(shí)候,操作系統(tǒng)自動(dòng)將硬盤分成兩個(gè)區(qū)域。一個(gè)是數(shù)據(jù)區(qū),存放文件數(shù)據(jù);另一個(gè)是 inode 區(qū)(inode table),存放 inode 所包含的信息。每個(gè) inode 節(jié)點(diǎn)的大小,一般是 128 字節(jié)或 256 字節(jié)。inode 節(jié)點(diǎn)的總數(shù),在格式化時(shí)就給定,一般是每1KB或每2KB就設(shè)置一個(gè) inode 節(jié)點(diǎn)。

          # 每個(gè)節(jié)點(diǎn)信息的內(nèi)容
          $ stat check_port_live.sh
            File: check_port_live.sh
            Size: 225           Blocks: 8          IO Block: 4096   regular file
          Device: 822h/2082d    Inode: 99621663    Links: 1
          Access: (0755/-rwxr-xr-x)  Uid: ( 1006/  escape)   Gid: ( 1006/  escape)
          Access: 2019-07-29 14:59:59.498076903 +0800
          Modify: 2019-07-29 14:59:59.498076903 +0800
          Change: 2019-07-29 23:20:27.834866649 +0800
           Birth: -

          # 磁盤的inode使用情況
          $ df -i
          Filesystem                 Inodes   IUsed     IFree IUse% Mounted on
          udev                     16478355     801  16477554    1% /dev
          tmpfs                    16487639    2521  16485118    1% /run
          /dev/sdc2               244162560 4788436 239374124    2% /
          tmpfs                    16487639       5  16487634    1% /dev/shm

          3. Docker 缺共享鏈接庫

          Docker 命令需要對(duì)/tmp 目錄下面有訪問權(quán)限

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

          # 提示錯(cuò)誤信息
          $ docker-compose --version
          error while loading shared libraries: libz.so.1: failed to map segment from shared object: Operation not permitted

          [解決方法] 后來發(fā)現(xiàn),是因?yàn)橄到y(tǒng)中 docker 沒有對(duì) /tmp 目錄的訪問權(quán)限導(dǎo)致,需要重新將其掛載一次,就可以解決了。

          # 重新掛載
          $ sudo mount /tmp -o remount,exec

          4. Docker 容器文件損壞

          對(duì) dockerd 的配置有可能會(huì)影響到系統(tǒng)穩(wěn)定

          [問題起因] 容器文件損壞,經(jīng)常會(huì)導(dǎo)致容器無法操作。正常的 docker 命令已經(jīng)無法操控這臺(tái)容器了,無法關(guān)閉、重啟、刪除。正巧,前天就需要這個(gè)的問題,主要的原因是因?yàn)橹匦聦?duì) docker 的默認(rèn)容器進(jìn)行了重新的分配限制導(dǎo)致的。

          # 操作容器遇到類似的錯(cuò)誤
          b'devicemapper: Error running deviceCreate (CreateSnapDeviceRaw) dm_task_run failed'

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

          # 1.關(guān)閉docker
          $ sudo systemctl stop docker

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

          # 3.重新整理容器元數(shù)據(jù)
          $ sudo thin_check /var/lib/docker/devicemapper/devicemapper/metadata
          $ sudo thin_check --clear-needs-check-flag /var/lib/docker/devicemapper/devicemapper/metadata

          # 4.重啟docker
          $ sudo systemctl start docker

          5. Docker 容器優(yōu)雅重啟

          不停止服務(wù)器上面運(yùn)行的容器,重啟 dockerd 服務(wù)是多么好的一件事

          [問題起因] 默認(rèn)情況下,當(dāng) Docker 守護(hù)程序終止時(shí),它會(huì)關(guān)閉正在運(yùn)行的容器。從 Docker-ce 1.12 開始,可以在配置文件中添加 live-restore 參數(shù),以便在守護(hù)程序變得不可用時(shí)容器保持運(yùn)行。需要注意的是 Windows 平臺(tái)暫時(shí)還是不支持該參數(shù)的配置。

          # Keep containers alive during daemon downtime
          $ sudo vim /etc/docker/daemon.yaml
          {
            "live-restore"true
          }

          # 在守護(hù)進(jìn)程停機(jī)期間保持容器存活
          $ sudo dockerd --live-restore

          # 只能使用reload重載
          # 相當(dāng)于發(fā)送SIGHUP信號(hào)量給dockerd守護(hù)進(jìn)程
          $ sudo systemctl reload docker

          # 但是對(duì)應(yīng)網(wǎng)絡(luò)的設(shè)置需要restart才能生效
          $ sudo systemctl restart docker

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

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

          6. Docker 容器無法刪除

          找不到對(duì)應(yīng)容器進(jìn)程是最嚇人的

          [問題起因] 今天遇到 docker 容器無法停止/終止/刪除,以為這個(gè)容器可能又出現(xiàn)了 dockerd 守護(hù)進(jìn)程托管的情況,但是通過 ps -ef <container id> 無法查到對(duì)應(yīng)的運(yùn)行進(jìn)程。哎,后來開始開始查 supervisor 以及 Dockerfile 中的進(jìn)程,都沒有。這種情況的可能原因是容器啟動(dòng)之后,之后,主機(jī)因任何原因重新啟動(dòng)并且沒有優(yōu)雅地終止容器。剩下的文件現(xiàn)在阻止你重新生成舊名稱的新容器,因?yàn)橄到y(tǒng)認(rèn)為舊容器仍然存在。

          # 刪除容器
          $ sudo docker rm -f f8e8c3..
          Error response from daemon: Conflict, cannot remove the default name of the container

          [解決方法] 找到 /var/lib/docker/containers/ 下的對(duì)應(yīng)容器的文件夾,將其刪除,然后重啟一下 dockerd 即可。我們會(huì)發(fā)現(xiàn),之前無法刪除的容器沒有了。

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

          # 重啟服務(wù)
          $ sudo systemctl restart docker.service

          7. Docker 容器中文異常

          容器存在問題話,記得優(yōu)先在官網(wǎng)查詢

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

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

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

          # 臨時(shí)解決
          docker exec -it some-mysql env LANG=C.UTF-8 /bin/bash

          # 永久解決
          docker run --name some-mysql \
              -e MYSQL_ROOT_PASSWORD=my-secret-pw \
              -d mysql:tag --character-set-server=utf8mb4 \
              --collation-server=utf8mb4_unicode_ci

          8. Docker 容器網(wǎng)絡(luò)互通

          了解 Docker 的四種網(wǎng)絡(luò)模型

          [問題起因] 在本機(jī)部署 Nginx 容器想代理本機(jī)啟動(dòng)的 Python 后端服務(wù)程序,但是對(duì)代碼服務(wù)如下的配置,結(jié)果訪問的時(shí)候一直提示 502 錯(cuò)誤。

          # 啟動(dòng)Nginx服務(wù)
          $ docker run -d -p 80:80 $PWD:/etc/nginx nginx

          server {
              ...
              location /api {
                  proxy_pass http://localhost:8080
              }
              ...
          }

          [解決方法] 后面發(fā)現(xiàn)是因?yàn)?nginx.conf 配置文件中的 localhost 配置的有問題,由于 Nginx 是在容器中運(yùn)行,所以 localhost 為容器中的 localhost,而非本機(jī)的 localhost,所以導(dǎo)致無法訪問。

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

          # 查詢宿主機(jī)IP地址 => 172.17.0.1
          $ ip addr show docker0
          docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
              link/ether 02:42:d5:4c:f2:1e brd ff:ff:ff:ff:ff:ff
              inet 172.17.0.1/16 scope global docker0
                 valid_lft forever preferred_lft forever
              inet6 fe80::42:d5ff:fe4c:f21e/64 scope link
                 valid_lft forever preferred_lft forever

          server {
              ...
              location /api {
                  proxy_pass http://172.17.0.1:8080
              }
              ...
          }

          當(dāng)容器使用 host 網(wǎng)絡(luò)時(shí),容器與宿主共用網(wǎng)絡(luò),這樣就能在容器中訪問宿主機(jī)網(wǎng)絡(luò),那么容器的 localhost 就是宿主機(jī)的 localhost 了。

          # 服務(wù)的啟動(dòng)方式有所改變(沒有映射出來端口)
          # 因?yàn)楸旧砼c宿主機(jī)共用了網(wǎng)絡(luò),宿主機(jī)暴露端口等同于容器中暴露端口
          $ docker run -d -p 80:80 --network=host $PWD:/etc/nginx nginxx

          9. Docker 容器總線錯(cuò)誤

          總線錯(cuò)誤看到的時(shí)候還是挺嚇人了

          [問題起因]docker 容器中運(yùn)行程序的時(shí)候,提示 bus error 錯(cuò)誤。

          # 總線報(bào)錯(cuò)
          $ inv app.user_op --name=zhangsan
          Bus error (core dumped)

          [解決方法] 原因是在 docker 運(yùn)行的時(shí)候,shm 分區(qū)設(shè)置太小導(dǎo)致 share memory 不夠。不設(shè)置 –shm-size 參數(shù)時(shí),docker 給容器默認(rèn)分配的 shm 大小為 64M,導(dǎo)致程序啟動(dòng)時(shí)不足。

          # 啟動(dòng)docker的時(shí)候加上--shm-size參數(shù)(單位為b,k,m或g)
          $ docker run -it --rm --shm-size=200m pytorch/pytorch:latest

          [解決方法] 還有一種情況就是容器內(nèi)的磁盤空間不足,也會(huì)導(dǎo)致 bus error 的報(bào)錯(cuò),所以清除多余文件或者目錄,就可以解決了。

          # 磁盤空間不足
          $ df -Th
          Filesystem     Type     Size  Used Avail UseMounted on
          overlay        overlay    1T    1T    0G 100% /
          shm            tmpfs     64M   24K   64M   1% /dev/shm

          10. Docker NFS 掛載報(bào)錯(cuò)

          總線錯(cuò)誤看到的時(shí)候還是挺嚇人了

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

          # 報(bào)錯(cuò)信息
          Traceback (most recent call last):
              ......
              File "xxx/utils/storage.py", line 34in xxx.utils.storage.LocalStorage.read_file
          OSError: [Errno 9] Bad file descriptor

          # 文件加鎖代碼
          ...
              with open(self.mount(path), 'rb'as fileobj:
                  fcntl.flock(fileobj, fcntl.LOCK_EX)
                  data = fileobj.read()
              return data
          ...

          [解決方法] 從下面的信息得知,要在 Linux 中使用 flock() 的話,就需要升級(jí)內(nèi)核版本到 2.6.11+ 才行。后來才發(fā)現(xiàn),這實(shí)際上是由 RedHat 內(nèi)核中的一個(gè)錯(cuò)誤引起的,并在 kernel-3.10.0-693.18.1.el7 版本中得到修復(fù)。所以對(duì)于 NFSv3NFSv4 服務(wù)而已,就需要升級(jí) Linux 內(nèi)核版本才能夠解決這個(gè)問題。

          # https://t.codebug.vip/questions-930901.htm
          $ In Linux kernels up to 2.6.11, flock() does not lock files over NFS (i.e.,
          the scope of locks was limited to the local system). [...] Since Linux 2.6.12,
          NFS clients support flock() locks by emulating them as byte-range locks on the entire file.

          11. Docker 默認(rèn)使用網(wǎng)段

          啟動(dòng)的容器網(wǎng)絡(luò)無法相互通信,很是奇怪!

          [問題起因] 我們?cè)谑褂?Docker 啟動(dòng)服務(wù)的時(shí)候,發(fā)現(xiàn)有時(shí)候服務(wù)之前可以相互連通,而有時(shí)間啟動(dòng)的多個(gè)服務(wù)之前卻出現(xiàn)了無法訪問的情況。究其原因,發(fā)現(xiàn)原來是因?yàn)槭褂玫膬?nèi)部私有地址網(wǎng)段不一致導(dǎo)致的。有點(diǎn)服務(wù)啟動(dòng)到了 172.17 - 172.31 的網(wǎng)段,有的服務(wù)跑到了 192.169.0 - 192.168.224 的網(wǎng)段,這樣導(dǎo)致服務(wù)啟動(dòng)之后出現(xiàn)無法訪問的情況。

          Docker默認(rèn)使用網(wǎng)段

          [解決方法] 上述問題的處理方式,就是手動(dòng)指定 Docker 服務(wù)的啟動(dòng)網(wǎng)段,就可以了。

          # 查看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": []
                  }
              }
          }

          12. Docker 服務(wù)啟動(dòng)串臺(tái)

          使用 docker-compose 命令各自啟動(dòng)兩組服務(wù),發(fā)現(xiàn)服務(wù)會(huì)串臺(tái)!

          [問題起因] 在兩個(gè)不同名稱的目錄目錄下面,使用 docker-compose 來啟動(dòng)服務(wù),發(fā)現(xiàn)當(dāng) A 組服務(wù)啟動(dòng)完畢之后,再啟動(dòng) B 組服務(wù)的時(shí)候,發(fā)現(xiàn) A 組當(dāng)中對(duì)應(yīng)的一部分服務(wù)又重新啟動(dòng)了一次,這就非常奇怪了!因?yàn)檫@個(gè)問題的存在會(huì)導(dǎo)致,A 組服務(wù)和 B 組服務(wù)無法同時(shí)啟動(dòng)。之前還以為是工具的 Bug,后來請(qǐng)教了“上峰”,才知道了原因,恍然大悟。

          # 服務(wù)目錄結(jié)構(gòu)如下所示
          A: /data1/app/docker-compose.yml
          B: /data2/app/docker-compose.yml

          [解決方法] 發(fā)現(xiàn) AB 兩組服務(wù)會(huì)串臺(tái)的原因,原來是 docker-compose 會(huì)給啟動(dòng)的容器加 label 標(biāo)簽,然后根據(jù)這些 label 標(biāo)簽來識(shí)別和判斷對(duì)應(yīng)的容器服務(wù)是由誰啟動(dòng)的、誰來管理的,等等。而這里,我們需要關(guān)注的 label 變量是 com.docker.compose.project,其對(duì)應(yīng)的值是使用啟動(dòng)配置文件的目錄的最底層子目錄名稱,即上面的 app 就是對(duì)應(yīng)的值。我們可以發(fā)現(xiàn), AB 兩組服務(wù)對(duì)應(yīng)的值都是 app,所以啟動(dòng)的時(shí)候被認(rèn)為是同一個(gè),這就出現(xiàn)了上述的問題。如果需要深入了解的話,可以去看對(duì)應(yīng)源代碼。

          Docker服務(wù)啟動(dòng)串臺(tái)


          # 可以將目錄結(jié)構(gòu)調(diào)整為如下所示
          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 命令提供的參數(shù) -p 來規(guī)避該問題的發(fā)生。

          # 指定項(xiàng)目項(xiàng)目名稱
          $ docker-compose -f ./docker-compose.yml -p app1 up -d

          13. Docker 命令調(diào)用報(bào)錯(cuò)

          在編寫腳本的時(shí)候常常會(huì)執(zhí)行 docker 相關(guān)的命令,但是需要注意使用細(xì)節(jié)!

          [問題起因] CI 更新環(huán)境執(zhí)行了一個(gè)腳本,但是腳本執(zhí)行過程中報(bào)錯(cuò)了,如下所示。通過對(duì)應(yīng)的輸出信息,可以看到提示說正在執(zhí)行的設(shè)備不是一個(gè) tty

          Docker命令調(diào)用報(bào)錯(cuò)

          隨即,查看了腳本發(fā)現(xiàn)報(bào)錯(cuò)地方是執(zhí)行了一個(gè) execdocker 命令,大致如下所示。很奇怪的是,手動(dòng)執(zhí)行或直接調(diào)腳本的時(shí)候,怎么都是沒有問題的,但是等到 CI 調(diào)用的時(shí)候怎么都是有問題。后來好好看下下面這個(gè)命令,注意到 -it 這個(gè)參數(shù)了。

          # 腳本調(diào)用docker命令
          docker exec -it <container_name> psql -Upostgres ......

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

          [解決方法] docker exec 的參數(shù) -t 是指 Allocate a pseudo-TTY 的意思,而 CI 在執(zhí)行 job 的時(shí)候并不是在 TTY 終端中執(zhí)行,所以 -t 這個(gè)參數(shù)會(huì)報(bào)錯(cuò)。

          Docker命令調(diào)用報(bào)錯(cuò)

          14. Docker 定時(shí)任務(wù)異常

          在 Crontab 定時(shí)任務(wù)中也存在 Docker 命令執(zhí)行異常的情況!

          [問題起因] 今天發(fā)現(xiàn)了一個(gè)問題,就是在備份 Mysql 數(shù)據(jù)庫的時(shí)候,使用 docker 容器進(jìn)行備份,然后使用 Crontab 定時(shí)任務(wù)來觸發(fā)備份。但是發(fā)現(xiàn)備份的 MySQL 數(shù)據(jù)庫居然是空的,但是手動(dòng)執(zhí)行對(duì)應(yīng)命令切是好的,很奇怪。

          # Crontab定時(shí)任務(wù)
          0 */6 * * * \
              docker exec -it <container_name> sh -c \
                  'exec mysqldump --all-databases -uroot -ppassword ......'

          [解決方法] 后來發(fā)現(xiàn)是因?yàn)閳?zhí)行的 docker 命令多個(gè) -i 導(dǎo)致的。因?yàn)?Crontab 命令執(zhí)行的時(shí)候,并不是交互式的,所以需要把這個(gè)去掉才可以??偨Y(jié)就是,如果你需要回顯的話則需要 -t 選項(xiàng),如果需要交互式會(huì)話則需要 -i 選項(xiàng)。

          15. Docker 變量使用引號(hào)

          compose 里邊環(huán)境變量帶不帶引號(hào)的問題!

          [問題起因] 使用過 compose 的同學(xué)可能都遇到過,我們?cè)诰帉憜?dòng)配置文件的時(shí)候,添加環(huán)境變量的時(shí)候到底是使用單引號(hào)、雙引號(hào)還是不使用引號(hào)。時(shí)間長(zhǎng)了,可能我們總是三者是一樣的,可以相互使用。但是,直到最后我們發(fā)現(xiàn)坑越來越多,越來越隱晦。

          反正我是遇到過很多是因?yàn)樘砑右?hào)導(dǎo)致的服務(wù)啟動(dòng)問題,后來得出的結(jié)論就是一律不適用引號(hào)。裸奔,體驗(yàn)前所未有的爽快!

          直到現(xiàn)在看到了 Github 中對(duì)應(yīng)的 issus 之后,才終于破案了。

          https://github.com/docker/compose/issues/2854

          # TESTVAR="test"
          在Compose中進(jìn)行引用TESTVAR變量,無法找到

          #
           TESTVAR=test
          在Compose中進(jìn)行引用TESTVAR變量,可以找到

          #
           docker run -it --rm -e TESTVAR="test" test:latest
          后來發(fā)現(xiàn)docker本身其實(shí)已經(jīng)正確地處理了引號(hào)的使用

          [解決方法] 得到的結(jié)論就是,因?yàn)?Compose 解析 yaml 配置文件,發(fā)現(xiàn)引號(hào)也進(jìn)行了解釋包裝。這就導(dǎo)致原本的 TESTVAR="test" 被解析成了 'TESTVAR="test"',所以我們?cè)谝玫臅r(shí)候就無法獲取到對(duì)應(yīng)的值?,F(xiàn)在解決方法就是,不管是我們直接在配置文件添加環(huán)境變量或者使用 env_file 配置文件,能不使用引號(hào)就不適用引號(hào)。

          16. Docker 刪除鏡像報(bào)錯(cuò)

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

          [問題起因] 清理服器磁盤空間的時(shí)候,刪除某個(gè)鏡像的時(shí)候提示如下信息。提示需要強(qiáng)制刪除,但是發(fā)現(xiàn)及時(shí)執(zhí)行了強(qiáng)制刪除依舊沒有效果。

          # 刪除鏡像
          $ docker rmi 3ccxxxx2e862
          Error response from daemon: conflict: unable to delete 3ccxxxx2e862 (cannot be forced) - image has dependent child images

          # 強(qiáng)制刪除
          $ dcoker rmi -f 3ccxxxx2e862
          Error response from daemon: conflict: unable to delete 3ccxxxx2e862 (cannot be forced) - image has dependent child images

          [解決方法] 后來才發(fā)現(xiàn),出現(xiàn)這個(gè)原因主要是因?yàn)?TAG,即存在其他鏡像引用了這個(gè)鏡像。這里我們可以使用如下命令查看對(duì)應(yīng)鏡像文件的依賴關(guān)系,然后根據(jù)對(duì)應(yīng) TAG 來刪除鏡像。

          # 查詢依賴 - image_id表示鏡像名稱
          $ docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=<image_id>)

          # 根據(jù)TAG刪除鏡像
          $ docker rmi -f c565xxxxc87f

          # 刪除懸空鏡像
          $ docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

          17. Docker 普通用戶切換

          切換 Docker 啟動(dòng)用戶的話,還是需要注意下權(quán)限問題的!

          [問題起因] 我們都知道在 Docker 容器里面使用 root 用戶的話,是不安全的,很容易出現(xiàn)越權(quán)的安全問題,所以一般情況下,我們都會(huì)使用普通用戶來代替 root 進(jìn)行服務(wù)的啟動(dòng)和管理的。今天給一個(gè)服務(wù)切換用戶的時(shí)候,發(fā)現(xiàn) Nginx 服務(wù)一直無法啟動(dòng),提示如下權(quán)限問題。因?yàn)閷?duì)應(yīng)的配置文件也沒有配置 var 相關(guān)的目錄,無奈 ???♀ !?

          # Nginx報(bào)錯(cuò)信息
          nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
          2020/11/12 15:25:47 [emerg] 23#23: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)

          [解決方法] 后來發(fā)現(xiàn)還是 nginx.conf 配置文件,配置的有問題,需要將 Nginx 服務(wù)啟動(dòng)時(shí)候需要的文件都配置到一個(gè)無權(quán)限的目錄,即可解決。

          user  www-data;
          worker_processes  1;

          error_log  /data/logs/master_error.log warn;
          pid        /dev/shm/nginx.pid;

          events {
              worker_connections  1024;
          }

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

              gzip               on;
              sendfile           on;
              tcp_nopush         on;
              keepalive_timeout  65;

              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;
          }

          文章作者: Escape
          文章鏈接: https://escapelife.github.io/posts/43a2bb9b.html

          推薦閱讀

          Docker基礎(chǔ)知識(shí)

          Docker 中級(jí)篇

          圖解 Docker 架構(gòu)

          Docker 常用命令,這些都要會(huì)!

          輕松帶你兩小時(shí)入門 Docker

          Docker 入門看這一篇就夠了!

          高中生也能讀懂的Docker入門教程

          Docker 入門終極指南:邊學(xué)邊用

          10 個(gè)冷門但又非常實(shí)用的 Docker 使用技巧!

          推薦 11 個(gè)極易上手的 Docker 實(shí)踐項(xiàng)目!

          看完這篇,Docker 你就入門了!

          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费一级毛片 | 亚洲男女内射在线播放 | 欧洲操逼免费看 | 在线看一区二区三区四区 | 欧美成人生活片一区三区 |