Docker容器進階(中)

2021-12-29 雲計算就該這麼學

收錄於話題 #雲計算核心課程 13個

使⽤端⼝轉發解決容器端⼝訪問問題

1、MySQL應⽤端⼝轉發

-p

創建應⽤容器的時候,⼀般會做端⼝映射,這樣是為了讓外部 能夠訪問這些容器⾥的應⽤。可以⽤多個-p指定多個端⼝映射關 系。

本例使⽤-p把本地3307轉發到容器的3306,其他參數需要查看發 布容器的⻚⾯提示

查看本地地址:
[root@qfedu.com ~]#ip a
 ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
qdisc pfifo_fast state UP qlen 1000
 link/ether 00:0c:29:0a:5b:8b brd ff:ff:ff:ff:ff:ff
 inet 192.168.245.134/24 brd 192.168.245.255 scope
global dynamic ens33
 valid_lft 1444sec preferred_lft 1444sec
運⾏容器:
[root@qfedu.com ~]# docker run --name mysql1 -p
3307:3306 -e MYSQL_ROOT_PASSWORD=123
daocloud.io/library/mysql
查看Ip地址:
[root@qfedu.com ~]# docker inspect mysql1 | grep
IPAddress
 "SecondaryIPAddresses": null,
 "IPAddress": "172.17.0.2",
 "IPAddress": "172.17.0.2",
通過本地IP:192.168.245.134的3307端⼝訪問容器mysql1內的數
據庫,出現如下提示恭喜你
[root@qfedu.com ~]# mysql -u root -p123 -h
192.168.245.134 -P3307
Welcome to the MariaDB monitor. Commands end with ;
or \g.
Your MySQL connection id is 3
Server version: 5.7.18 MySQL Community Server (GPL)
Copyright (c) 2000, 2016, Oracle, MariaDB
Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear
the current input statement.
MySQL [(none)]>

2、Redis應⽤端⼝轉發

-P

Docker 會隨機映射⼀個 49000~49900 的端⼝到內部容器開 放的⽹絡端⼝。如下:

[root@qfedu.com ~]# docker images
REPOSITORY TAG IMAGE ID CREATED 
 SIZE
docker.io/redis latest e4a35914679d 2
weeks ago 182.9 MB
[root@qfedu.com ~]# docker run --name myredis -P -d
docker.io/redis
805d0e21e531885aad61d3e82395210b50621f1991ec4b7f9a0e
25c815cc0272
[root@qfedu.com ~]# docker ps
CONTAINER ID IMAGE COMMAND 
CREATED STATUS PORTS NAMES
805d0e21e531 docker.io/redis "dockerentrypoint.sh" 4 seconds ago Up 3 seconds 
0.0.0.0:32768->6379/tcp myredis
從上⾯的結果中可以看出,本地主機的32768端⼝被映射到了redis容
器的6379端⼝上,也就是說訪問本機的32768
端⼝即可訪問容器內redis端⼝。
測試看下,登陸redis容器,隨意寫個數據
[root@qfedu.com ~]# docker run --rm -it --name
myredis2 --link myredis:redisdb docker.io/redis
/bin/
bash
root@be44d955d6f4:/data[root@qfedu.com ~]# redis-cli
-h redisdb -p 6379
redisdb:6379> set wing 123
OK
redisdb:6379>
在別的機器上通過上⾯映射的端⼝32768連接這個容器的redis
[root@qfedu.com ~]# redis-cli -h 192.168.245.134 -p
32768
192.168.1.23:32768> get wing
"123"

1、容器卷操作

容器卷是容器和宿主機之間的⽂件共享⽅式之⼀

新卷只能在容器創建過程當中掛載
[root@qfedu.com ~]# docker run -it --name="voltest"
-v /tmp:/test daocloud.io/library/centos:5
/bin/bash
共享其他容器的卷:
[root@qfedu.com ~]# docker run -it --volumes-from
bc4181 daocloud.io/library/centos:5 /bin/bash
實際應⽤中可以利⽤多個-v選項把宿主機上的多個⽬錄同時共享給新建
容器:
⽐如:
[root@qfedu.com ~]# docker run -it -v /abc:/abc -v
/def:/def 1ae9
[root@qfedu.com ~]# docker run -v
/vol/index.html:/usr/share/nginx/html/index.html -it
nginx /bin/bash

注意:

如果是⽂件共享,數據不能同步更新

2、Volume【擴展閱讀】

容器技術使⽤了 rootfs 機制和 Mount Namespace,構建出了⼀ 個同宿主機完全隔離開的⽂件系統環境。這時候,就需要考慮這樣兩個 問題:

容器⾥進程新建的⽂件,怎麼才能讓宿主機獲取到?

宿主機上的⽂件和⽬錄,怎麼才能讓容器⾥的進程訪問到?

這正是 Docker Volume 要解決的問題:Volume 機制,允許你將 宿主機上指定的⽬錄或者⽂件,掛載到容器⾥⾯進⾏讀取和修改操作。

在 Docker 項⽬⾥,它⽀持兩種 Volume 聲明⽅式,可以把宿主機 ⽬錄掛載進容器的 /test ⽬錄當中:

[root@qfedu.com ~]# docker run -v /test ...
[root@qfedu.com ~]# docker run -v /home:/test ...

這兩種聲明⽅式的本質是相同的:都是把⼀個宿主機的⽬錄掛載進 了容器的 /test ⽬錄。

第⼀種情況沒有顯示聲明宿主機⽬錄,Docker 就會默認在宿主機 上創建⼀個臨時⽬錄 /var/lib/docker/volumes/[VOLUME_ID]/_data, 然後把它掛載到容器的 /test ⽬錄上。

第⼆種情況,Docker 就直接把宿主機的 /home ⽬錄掛載到容器 的 /test ⽬錄上。

那麼,Docker ⼜是如何做到把⼀個宿主機上的⽬錄或者⽂件,掛 載到容器⾥⾯去呢?難道⼜是 Mount Namespace 的⿊科技嗎?

實際上,並不需要這麼麻煩。

已經介紹過,當容器進程被創建之後,儘管開啟了 Mount Namespace,但是在它執⾏ chroot(或者 pivot_root)之前,容器進 程⼀直可以看到宿主機上的整個⽂件系統。

⽽宿主機上的⽂件系統,也⾃然包括了要使⽤的容器鏡像。這個鏡 像的各個層,保存在 /var/lib/docker/aufs/diff ⽬錄下,在容器進程啟 動後,它們會被聯合掛載在 /var/lib/docker/aufs/mnt/ ⽬錄中,這樣 容器所需的 rootfs 就準備好了。

所以,只需要在 rootfs 準備好之後,在執⾏ chroot 之前,把 Volume 指定的宿主機⽬錄(⽐如 /home ⽬錄),掛載到指定的容器 ⽬錄(⽐如 /test ⽬錄)在宿主機上對應的⽬錄(即 /var/lib/docker/aufs/mnt/[可讀寫層 ID]/test)上,這個 Volume 的掛 載⼯作就完成了。

由於執⾏這個掛載操作時,"容器進程"已經創建了,也就意味著此 時 Mount Namespace 已經開啟了。所以,這個掛載事件只在這個容 器⾥可⻅。你在宿主機上,是看不⻅容器內部的這個掛載點的。這就保 證了容器的隔離性不會被 Volume 打破。

注意:這⾥提到的 " 容器進程 ",是 Docker 創建的⼀個容器初始 化進程 (dockerinit),⽽不是應⽤進程 (ENTRYPOINT + CMD)。dockerinit 會負責完成根⽬錄的準備、掛載設備和⽬錄、配置 hostname 等⼀系列需要在容器內進⾏的初始化操作。最後,它通過 execv() 系統調⽤,讓應⽤進程取代⾃⼰,成為容器⾥的 PID=1 的進 程。

⽽這⾥要使⽤到的掛載技術,就是 Linux 的綁定掛載(bind mount)機制。它的主要作⽤就是,允許你將⼀個⽬錄或者⽂件,⽽ 不是整個設備,掛載到⼀個指定的⽬錄上。並且,這時你在該掛載點上 進⾏的任何操作,只是發⽣在被掛載的⽬錄或者⽂件上,⽽原掛載點的 內容則會被隱藏起來且不受影響。

其實,如果你了解 Linux 內核的話,就會明⽩,綁定掛載實際上是 ⼀個 inode 替換的過程。在 Linux 作業系統中,inode 可以理解為存 放⽂件內容的"對象",⽽ dentry,也叫⽬錄項,就是訪問這個 inode 所使⽤的"指針"

mount --bind /home /test,會將 /home 掛載到 /test 上。其實相 當於將 /test 的 dentry,重定向到了 /home 的 inode。這樣當修改 /test ⽬錄時,實際修改的是 /home ⽬錄的 inode。這也就是為何,⼀ 旦執⾏ umount 命令,/test ⽬錄原先的內容就會恢復:因為修改真正發⽣在的,是 /home ⽬錄⾥。

進程在容器⾥對這個 /test ⽬錄進⾏的所有操作,都實際發⽣在宿 主機的對應⽬錄(⽐如,/home,或者 /var/lib/docker/volumes/[VOLUME_ID]/_data)⾥,⽽不會影響容器 鏡像的內容。

這個 /test ⽬錄⾥的內容,既然掛載在容器 rootfs 的可讀寫層,它 會不會被 docker commit 提交掉呢?

也不會。

原因前⾯提到過。容器的鏡像操作,⽐如 docker commit,都是 發⽣在宿主機空間的。⽽由於 Mount Namespace 的隔離作⽤,宿主 機並不知道這個綁定掛載的存在。所以,在宿主機看來,容器中可讀寫 層的 /test ⽬錄(/var/lib/docker/aufs/mnt/[可讀寫層 ID]/test),始 終是空的。

不過,由於 Docker ⼀開始還是要創建 /test 這個⽬錄作為掛載 點,所以執⾏了 docker commit 之後,新產⽣的鏡像⾥,會多出來⼀ 個空的 /test ⽬錄。畢竟,新建⽬錄操作,⼜不是掛載操作,Mount Namespace 對它可起不到"障眼法"的作⽤。

1.啟動⼀個 helloworld 容器,給它聲明⼀個 Volume,掛載在容
器⾥的 /test ⽬錄上:
[root@qfedu.com ~]# docker run -d -v /test
helloworld
cf53b766fa6f
2.容器啟動之後,查看⼀下這個 Volume 的 ID:
[root@qfedu.com ~]# docker volume ls
DRIVER VOLUME NAME
local 
cb1c2f7221fa9b0971cc35f68aa1034824755ac44a034c0c0a1d
d318838d3a6d
3.使⽤這個 ID,可以找到它在 Docker ⼯作⽬錄下的 volumes 路
徑:
[root@qfedu.com ~]# ls
/var/lib/docker/volumes/cb1c2f7221fa/_data/
這個 _data ⽂件夾,就是這個容器的 Volume 在宿主機上對應的臨
時⽬錄了。
4.在容器的 Volume ⾥,添加⼀個⽂件 text.txt:
[root@qfedu.com ~]# docker exec -it cf53b766fa6f
/bin/sh
cd test/
touch text.txt
5.再回到宿主機,就會發現 text.txt 已經出現在了宿主機上對應的
臨時⽬錄⾥:
[root@qfedu.com ~]# ls
/var/lib/docker/volumes/cb1c2f7221fa/_data/
text.txt
可是,如果你在宿主機上查看該容器的可讀寫層,雖然可以看到這個
/test ⽬錄,但其內容是空的:
[root@qfedu.com ~]# ls
/var/lib/docker/aufs/mnt/6780d0778b8a/test

可以確認,容器 Volume ⾥的信息,並不會被 docker commit 提 交掉;但這個掛載點⽬錄 /test 本身,則會出現在新的鏡像當中。以上 內容,就是 Docker Volume 的核⼼原理了。

Docker 容器"全景圖":

⼀個"容器",實際上是⼀個由 Linux Namespace、Linux Cgroups 和 rootfs 三種技術構建出來的進程的隔離環境。

相關焦點

  • 使用Docker安裝Tomcat、Nginx、Redis容器
    收錄於話題 #Docker容器入門與進階實戰> 今天本篇文章為大家分享Docker安裝Tomcat容器、Nginx容器、Redis容器的系列課程,歡迎大家一起觀看閱讀哦!使用Do
  • Docker 工作原理及容器化簡易指南
    甚至可以同一臺機器上的不同容器中運行具有相同 PID 的進程。同樣的,兩個不同容器中的應用程式可以使用相同的埠。Cgroups 允許對可用資源設置限制和約束。例如,您可以在一臺擁有 16 G 內存的計算機上創建一個 Namespace ,限制其內部進程可用內存為 1 GB。到這,您可能已經猜到 Docker 的工作原理了。
  • 如何在Ubuntu中安裝Docker和運行 Docker容器
    Docker使用容器可以更輕鬆地創建,部署和運行應用程式。使用容器,開發人員(和系統管理員)可以使用運行應用程式所需的一切來打包應用程式 - 代碼,運行時,庫,環境變量和配置文件,並將它們作為一個包發送出去。 是的,真是太好了!在本文中,我們將向您展示如何安裝Docker CE(Community Edition),在Ubuntu發行版上創建和運行Docker容器。
  • Docker系列教程:如何在 Docker 容器中運行 Nginx
    Docker 是一個容器化平臺,用於將您的應用程式打包成一個易於管理的容器映像。先決條件Docker 應該已安裝並在您的系統上本地運行。您需要一個 root 帳戶,或者用戶可以運行 sudo 命令。在 Docker 中設置 Nginx拉取鏡像首先,我們將拉取官方的 Nginx 鏡像。
  • volume 生命周期管理 - 每天5分鐘玩轉 Docker 容器技術(44)
    前面我們主要關注的是 volume 的創建、共享和使用,本節將討論如何備份、恢復、遷移和銷毀 volume。備份因為 volume 實際上是 host 文件系統中的目錄和文件,所以 volume 的備份實際上是對文件系統的備份。還記得前面我們是如何搭建本地 Registry 的嗎?
  • Docker容器的管理
    還有一點特別需要提醒的是:docker run 鏡像名 如果鏡像文件在本地不存在,就會在線去下載該鏡像的資源信息。docker的容器啟動成功後,使用docker ps -a可以查看容器的ID記錄信息。:#運行hello-world的容器[root@wuyaShare ~]# docker run hello-worldUnable to find image 'hello-world:latest' locallylatest: Pulling from library/hello-world#查看運行容器的記錄信息[root@wuyaShare
  • 怎樣在Python中操作Docker容器?
    如果你能讓那些棘手的應用在Linux環境下運行起來,你就可以通過sidomo,毫不費力地就在Python中調用這個應用。目前很多人使用容器Docker Daemon API來管理承載著他們應用的容器。 (Kubernetes / Mesos 就是很好的例子)。
  • Docker for 開發:容器化你的應用
    當我們開始編輯原始碼並在容器之間進行通信時,我將介紹一個運行Webpack的開發伺服器的進階的通用React.js應用程式,其中包含熱模塊重新加載,MongoDB資料庫等。但是,通常在您選擇的IDE中運行終端或獨立運行終端。為了讓Docker與另一個終端/提示進行交互,您需要通過運行「docker-machine env」來初始化Docker env。文本顯示的末尾是一個命令,您需要從該同一終端中複製該命令以初始化Docker環境。下一步是獲取要容器化的開發應用程式的原始碼。
  • 微服務中的容器技術---Docker(一),Docker的安裝和使用
    概述在微服系統中,因為服務特別多,如果手動部署以及啟動、重啟等工作會比較繁瑣,這裡會涉及到自動化部署,自動化部署就需要用到容器技術
  • Docker容器互聯方法
    雖然有許多方法可以連接容器們,可是我將並不會試著去將其全部討論在內。但是在這一系列的方法中,我們將看看那些常用的做法。雖然看起來是很淺顯,但是這對於與Docker成天打交道的朋友來說,理解這些技術及底層的設計理念就顯得非常地重要了。
  • Docker 系列教程:輕鬆在 Docker 容器中運行 MySQL 圖文指南
    本指南逐步解釋了如何在幾分鐘內設置在 Docker 容器中運行新的 MySQL 伺服器。Docker 的一大優點是您可以快速使用它來試用應用程式,而無需直接在您的機器上安裝它。您可以使用 Docker 在容器中運行資料庫,就像它是遠程伺服器一樣,並測試您的應用程式如何與其交互。使用 Docker 容器運行 MySQL 是一種廣泛使用的機制。
  • Docker容器中使用GPU
    背景容器封裝了應用程式的依賴項,以提供可重複和可靠的應用程式和服務執行,而無需整個虛擬機的開銷。
  • 如何在Docker容器中運行GUI程序
    它沒有語言支持、框架或者打包系統的限制,並可以運行在任何地方、任何時候,從小型的家用電腦到高端的伺服器都可以運行。這讓人們可以打包不同的包用於部署和擴展網絡應用,資料庫和後端服務而不必依賴於特定的棧或者提供商。 下面是我們該如何在Docker容器中運行GUI程序的簡單步驟。本教程中,我們會用Firefox作為例子。1.
  • Docker容器入門指北
    使用Docker鏡像工作Docker容器從Docker鏡像中工作,它默認從Docker hub拉取這些需要的鏡像。運行Docker容器的大多數應用和linux的發行版所需要的鏡像image都能在Docker hub找到。
  • Docker容器中的備份、恢復、遷移、導入、導出
    Docker打包應用以及依賴包到一個輕量級、可移植的容器中,然後發布到任何流行的Linux機器上,也可以實現虛擬化,Docker是跨平臺的容器引擎,支持Windows、MAC OS、Linux等。容器是完全使用沙箱機制,相互之間不會有任何接口,實現了資源隔離技術,容器內的資源互不影響,更重要的是容器性能開銷極低。
  • docker容器由淺入深解析
    個人認為容器技術應該作為程式設計師的必備技術,其作為工具不僅能夠大大提供我們的工作效率,其實現原理也值得我們好好學習和借鑑。本篇就為大家介紹下容器的使用以及容器鏡像原理的解析。使用介紹我們在日常工作中,想本地安裝一個資料庫,安裝一個redis。各種找資源,下載,編譯,安裝,這些步驟麻煩,學會使用docker,一條命令其實就可以搞定。
  • Docker Swarm在生產環境中的進階指南
    當在本地開發環境中使用Docker,或者已經在單臺生產伺服器上部署Docker,卻發現它不足以支撐更多的流量。應該如何解決?本文將給出若干提示,如何在生產環境中使用Docker Swarm。附:如果對Swarm不熟悉,請查看之前的文章《你可能需要知道的關於Docker Swarm的經驗分享》。
  • docker容器中的文件莫名其妙被刪了?
    問題的表象nginx容器跑一段時間後,再訪問http服務就403了,而且會不定期出現
  • 玩轉docker容器編排調度 docker-compose、docker-swarm
    容器啟動後,同屬一個網絡下(默認一般是橋接)的容器彼此能根據對方的name彼此ping通。使用docker-compose時,他會為我們新創建一個虛擬網卡。app中的容器啟動後都會加入這個虛擬網絡中。後來我們學著通過volume將容器中應用的配置文件掛載到宿主機實現簡單的定製化配置,然後docker run 啟動容器再後來我們學習了Dockerfile,自定義鏡像,實現了將我們本地打包好的應用做成鏡像,然後docker run 啟動容器。
  • Docker 容器化部署技術
    Docker是開源的應用容器引擎,開發者可以將應用及其依賴的軟體一起打包到容器中,實現一次部署到處運行的效果。當應用切換伺服器時,再次部署相當於複製一個文件的操作,節約大量的安裝部署時間。Docker容器技術優勢1、啟動快、解決虛擬機資源消耗問題啟動容器相當於啟動本機一個進程,啟動速度快。