<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                :-: ![ChMkJlXRnDCIH09oAACwpjAygMYAAAMuAH-4nMAALC-242](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/ChMkJlXRnDCIH09oAACwpjAygMYAAAMuAH-4nMAALC-242.png) [toc] ## Docker的起源 2010年,美國幾個年輕人成立dotcloud,基于linux的LXC容器技術 后期更名為Docker,為了更有影響力,2013決定開源。 ![ChMkJ1XRnC2IQ7KBAAJJ3hbQKYoAAAMuAGX_dUAAkn2298](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/ChMkJ1XRnC2IQ7KBAAJJ3hbQKYoAAAMuAGX_dUAAkn2298.png) ![ChMkJ1XRnOaISYkOAAHO_HkoN04AAAMugH1QcAAAc8U241](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/ChMkJ1XRnOaISYkOAAHO_HkoN04AAAMugH1QcAAAc8U241.png) ## Docker三大核心組件 - 鏡像(images):類似虛擬機鏡像 - 倉庫(Repository):集中存放鏡像的地方。每個服務器上可以有多個倉庫。 - 容器(containers):鏡像的一個運行實例,類似linux系統環境,運行和隔離應用 ## Docker核心技術 ### NameSpace 簡單來說,**Namespace 可以為容器提供系統資源隔離能力**。 當然,這樣講過于籠統,我們來舉個例子:假如一個容器中的進程需要使用 root 權限,出于安全考慮,我們不可能把宿主機的 root 權限給他。但是通過 Namespace 機制,我們可以隔離宿主機與容器的真實用戶資源,謊稱一個普通用戶就是 root,**騙**過這個程序。從這個角度看,**Namespace 就是內核對進程說謊的機制**,目前(Linux最新的穩定版本為5.6),內核可以說的**謊話**有 8 種: <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220313132517638.png" alt="image-20220313132517638" style="zoom:50%;" /> 感受 Namespace <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220313133410216.png" alt="image-20220313133410216" style="zoom:50%;" /> ### CGroup Namespace 只能做到系統資源維度的隔離,無法做到硬件資源的控制。我們需要使用一種機制 **Cgroup**,指定容器應用最大占用多少資源。 Linux cgroups 的全稱是 Linux Control Groups,它是 Linux 內核的特性,主要作用是限制、記錄和隔離進程組(process groups)使用的物理資源(CPU、Memory、IO 等)。 因此 CGroup 需要考慮如何抽象這兩種概念:**進程和資源,同時如何組織自己的結構**。CGroup 機制中有以下幾個基本概念: - **task**:任務,對應于系統中運行的一個實體,下文統稱進程; - **subsystem**:子系統,具體的資源控制器(resource class 或者 resource controller),控制某個特定的資源使用; - **cgroup**:控制組,一組任務和子系統的關聯關系,表示對這些任務進行怎樣的資源管理策略; - **hierarchy**:層級樹,由一系列 CGroup 組成的樹形結構。每個節點都是一個 CGroup ,CGroup 可以有多個子節點,子節點默認會繼承父節點的屬性。系統中可以有多個 hierarchy 在 Linux 環境中,我們可以執行 `ls -al /sys/fs/cgroup/` 查看當前系統的 `Cgroup: <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220313135429910.png" alt="image-20220313135429910" style="zoom:50%;" /> 我們看到目錄中有若干個子目錄,除了 systemd 目錄,其他的一個子目錄對應一個子系統,子系統功能如下所示。 <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220313135521688.png" alt="image-20220313135521688" style="zoom:50%;" /> **容器的本質就是一個特殊的進程** ## Docker的安裝 參考文檔: https://mirrors.tencent.com/help/docker-ce.html https://developer.aliyun.com/article/110806 https://docs.docker.com/engine/install/centos/ (官方文檔) ### 1、卸載老版本 前提需要卸載系統內老版本Docker,如果是新系統可跳過此步驟 ```bash yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine ``` ### 2、安裝依賴 ```bash yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 ``` ### 3、添加docker鏡像倉庫 ```bash wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo ``` ### 4、替換倉庫地址 > 阿里云倉庫地址: ```bash yum-config-manager \ --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo ``` > 騰訊云倉庫地址: ```bash sed -i 's+download.docker.com+mirrors.cloud.tencent.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo ``` ### 5、更新yum包索引 ```bash yum makecache fast ``` ### 6、安裝docker CE ```bash yum install docker-ce docker-ce-cli containerd.io -y ``` 選擇版本安裝: ```bash yum list docker-ce.x86_64 --showduplicates | sort -r ``` #從高到低列出Docker-ce的版本 yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io 例如: ```bash yum install docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io ``` 使用官方安裝腳本自動安裝: ```bash curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun ``` ### 7、啟動docker ```bash systemctl start docker ``` #### 7.1 驗證 通過運行hello-world 映像來驗證是否正確安裝了Docker Engine 。 ```bash docker run hello-world ``` ### 8、卸載 *列出docker包的具體名字 ```bash yum list installed | grep docker yum remove docker-ce docker-ce-cli containerd.io ``` 以上命令只會刪除docker運行環境,并不會刪除鏡像,容器,卷文件,以及用戶創建的配置文件。 刪除資源目錄: ```bash rm -rf /var/lib/docker ``` ### 9、鏡像加速 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors?accounttraceid=4f5db75ebc8b410fb30d4bcbac0f5a5cvdpx 使用私人鏡像加速器地址,如使用阿里云的鏡像加速器:登錄阿里云->產品->搜索"容器鏡像服務"->鏡像庫->鏡像加速器 Docker 使用 /etc/docker/daemon.json ```bash vim /etc/docker/daemon.json { "registry-mirrors": ["https://9s0l9akh.mirror.aliyuncs.com"] } systemctl daemon-reload systemctl restart docker ``` ==**問題:**== yum install docker-ce docker-ce-cli containerd.io -y 報錯如圖: ![](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/warning-1.png) ```bash #解決 /etc/yum.repos.d/docker-ce.repo [centos-extras] name=Centos extras - $basearch baseurl=http://mirror.centos.org/centos/7/extras/x86_64 enabled=1 gpgcheck=1 gpgkey=http://centos.org/keys/RPM-GPG-KEY-CentOS-7 yum -y install slirp4netns fuse-overlayfs container-selinux yum -y install docker-ce docker-ce-cli containerd.io ``` ## Docker的常用命令 ### 幫助命令 ```bash docker version #顯示docker的版本信息 docker info #顯示docker的詳細信息 docker 命令 --help #幫助命令 ``` 查看docker日志 ```bash cat /var/log/docker ``` ### 鏡像命令 ![image-20220312111656363](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220312111656363.png) ```bash docker images #查看當前所有鏡像 #解釋 REPOSITORY 鏡像的倉庫源 TAG 鏡像標簽 IMAGE ID 鏡像的ID CREATED 鏡像的創建時間 SIZE 鏡像的大小 -a 列出本地所有鏡像,含中間映像層 -q 只顯示鏡像ID 所有鏡像存儲在/var/lib/docker ``` 搜索鏡像 ```bash docker search tomcat #去鏡像倉庫搜索鏡像 docker search nginx docker search mysql --filter=stars=3000 ``` 下載鏡像 ```bash docker pull centos #下載鏡像[:tag] [root@bothtech ~]# docker pull mysql Using default tag: latest #如果不寫tag默認為latest latest: Pulling from library/mysql 72a69066d2fe: Pull complete #分層下載、image聯合文件系統 93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d5d7efb64e: Pull complete ac563158d721: Pull complete d2ba16033dad: Pull complete 688ba7d5c01a: Pull complete 00e060b6d11d: Pull complete 1c04857f594f: Pull complete 4d7cfa90e6ea: Pull complete e0431212d27d: Pull complete Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 #簽名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest #真實地址 ``` 指定版本 ```bash [root@bothtech ~]# docker pull mysql:5.7.37 5.7.37: Pulling from library/mysql 15115158dd02: Pull complete d733f6778b18: Pull complete 1cc7a6c74a04: Pull complete c4364028a805: Pull complete 82887163f0f6: Pull complete 28abcb7f57e0: Pull complete 46d27a431703: Pull complete 146a7517cdca: Pull complete ac645a526e45: Pull complete a292dcc315cc: Pull complete ff70b7ef8a8b: Pull complete Digest: sha256:66d52e6baa8093820c09fec56992a5ee734f17e9fad8ef5ffc31597b231bd048 Status: Downloaded newer image for mysql:5.7.37 docker.io/library/mysql:5.7.37 ``` 刪除鏡像 通過id和名字都可以進行刪除 刪除一個或者多個: ```bash docker rmi -f id1 id2 #支持刪除多個,使用空格分割 ``` 刪除全部鏡像: ```bash docker rmi -f (docker images -qa) ``` ### 容器命令 新建容器并啟動 ```bash docker run [可選參數] image --name=‘name’ 容器名字,區分容器 -d 后臺方式運行 -it 使用交互方法,進入容器查看內容 -p 指定容器端口 #-p ip:宿主機端口:容器端口 #-p 宿主機端口:容器端口 (常用) #-p 容器端口 -P 隨機指定端口 -v <空/宿主機目錄路徑/文件>:<容器目錄路徑或文件> # 三種掛載: 匿名掛載、具名掛載、指定路徑掛載 --restart=always 容器隨docker啟動而運行 (如果忘記添加,可以后續通過“docker container update --restart=always 容器名” 來更新參數) ``` 運行并進入容器centos ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it centos /bin/bash [root@bd1b8900c547 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var ``` 退出容器命令 ```bash #exit 停止并退出容器(后臺方式運行則僅退出) #Ctrl+P+Q 不停止容器退出 ``` 列出運行過的容器命令 ```bash #docker ps # 列出當前正在運行的容器 -a # 列出所有容器的運行記錄 -n=? # 顯示最近創建的n個容器 -q # 只顯示容器的編號 docker ps -qaf 'name=cpnginx' #從容器名稱獲取容器ID [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bca129320bb5 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago optimistic_shtern bd1b8900c547 centos "/bin/bash" 6 minutes ago Exited (0) 5 minutes ago cool_tesla cf6adbf1b506 bf756fb1ae65 "/hello" 5 hours ago Exited (0) 5 hours ago optimistic_darwin ``` 刪除容器命令 ```bash docker rm 容器id #刪除指定的容器,不能刪除正在運行的容器,強制刪除使用 rm -f docker rm -f (docker ps -aq) #刪除所有的容器 docker ps -a -q|xargs docker rm #刪除所有的容器 ``` 啟動和停止容器命令 ```bash docker start 容器id #啟動容器,關閉的容器重新啟動 docker restart 容器id #重啟容器 docker stop 容器id #停止當前運行的容器 docker kill 容器id #強制停止當前容器 ``` ### 其他常用命令 查看容器ip ```bash [root@ecs-b8ca-0817460 ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' php-web 172.17.0.3 [root@ecs-b8ca-0817460 ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' nginx-web 172.17.0.2 ``` 查看容器的端口映射: ```bash [root@bothtech ~]# docker port mysql-web ``` 查看容器的目錄映射: ```bash [root@bothtech ~]# docker inspect mysql-web ``` 日志查看 ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker logs --help Usage: docker logs [OPTIONS] CONTAINER Fetch the logs of a container Options: --details Show extra details provided to logs -f, --follow Follow log output --since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) -n, --tail string Number of lines to show from the end of the logs (default "all") -t, --timestamps Show timestamps --until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) 常用: docker logs -tf 容器id docker logs --tail number 容器id #num為要顯示的日志條數 #docker容器后臺運行,必須要有一個前臺的進程,否則會自動停止 #編寫shell腳本循環執行,使得centos容器保持運行狀態 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d centos /bin/sh -c "while true;do echo hi;sleep 5;done" c703b5b1911ff84d584390263a35707b6024816e1f46542b61918a6327a570dc [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c703b5b1911f centos "/bin/sh -c 'while t…" 13 seconds ago Up 10 seconds pedantic_banach [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker logs -tf --tail 10 c703b5b1911f 2020-12-27T03:34:07.255599560Z hi 2020-12-27T03:34:12.257641517Z hi 2020-12-27T03:34:17.259706294Z hi 2020-12-27T03:34:22.261693707Z hi 2020-12-27T03:34:27.262609289Z hi 2020-12-27T03:34:32.267862677Z hi 2020-12-27T03:34:37.270382873Z hi 2020-12-27T03:34:42.272414182Z hi 2020-12-27T03:34:47.274823243Z hi 2020-12-27T03:34:52.277419274Z hi ``` 查看容器中進程信息 ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker top c703b5b1911f UID PID PPID C STIME TTY TIME CMD root 11156 11135 0 11:31 ? 00:00:00 /bin/sh -c while true;do echo hi;sleep 5;done root 11886 11156 0 11:43 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5 ``` 查看容器的元數據 ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker inspect 容器id ``` 進入正在運行中的容器 因為通常我們的容器都是使用后臺方式來運行的,有時需要進入容器修改配置 方式一: ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it c703b5b1911f /bin/bash [root@c703b5b1911f /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@c703b5b1911f /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 03:31 ? 00:00:00 /bin/sh -c while true;do echo hi;sleep 5;done root 279 0 0 03:54 pts/0 00:00:00 /bin/bash root 315 1 0 03:56 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5 root 316 279 0 03:56 pts/0 00:00:00 ps -ef ``` 方式二: ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker attach c703b5b1911f ``` #docker exec 進入容器后開啟一個新的終端,可以在里面操作 #docker attach 進入容器正在執行的終端,不會啟動新的進程 拷貝操作命令 ```bash #拷貝容器的文件到主機中 docker cp 容器id:容器內路徑 目的主機路徑 #拷貝宿主機的文件到容器中 docker cp 目的主機路徑 容器id:容器內路徑 ``` ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it c703b5b1911f /bin/bash [root@c703b5b1911f /]# cd home [root@c703b5b1911f home]# ls #touch 新建文件 [root@c703b5b1911f home]# touch test.java [root@c703b5b1911f home]# ls test.java [root@c703b5b1911f home]# exit exit [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c703b5b1911f centos "/bin/sh -c 'while t…" 35 minutes ago Up 35 minutes pedantic_banach [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker cp c703b5b1911f:/home/test.java /home [root@iZwz99sm8v95sckz8bd2c4Z ~]# ls /home hai pan test.java ``` <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/src=http___img-blog.csdnimg.cn_img_convert_e86543bb903f3f989485e4cb5e3e194e.png&refer=http___img-blog.csdnimg.webp" alt="src=http___img-blog.csdnimg.cn_img_convert_e86543bb903f3f989485e4cb5e3e194e.png&refer=http___img-blog.csdnimg" style="zoom:70%;" /> ### docker容器中安裝vim 、telnet、ifconfig, ping命令 ```java apt-get update apt-get install vim 安裝vim apt-get install telnet 安裝telnet apt-get install net-tools 安裝ifconfig apt-get install iputils-ping 安裝ping apt-get install iproute2 安裝ip addr ``` ## 圖形化管理工具 ### Portaniner安裝 Portaniner是Docker的圖形化管理工具,類似的工具還有Rancher(CI/CD再用) 下載運行Portaniner鏡像并運行,設置宿主機映射端口為8088,如果為云服務器需要開放端口進行訪問 ```java [root@localhost conf]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer Unable to find image 'portainer/portainer:latest' locally latest: Pulling from portainer/portainer 94cfa856b2b1: Pull complete 49d59ee0881a: Pull complete a2300fd28637: Pull complete Digest: sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f Status: Downloaded newer image for portainer/portainer:latest 8c525a0137be22965bd1e3944da622a2c4248f8ad20883f4b3ea4f8a6b11e163 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7789d4505a00 portainer/portainer "/portainer" 6 seconds ago Up 5 seconds 0.0.0.0:8088->9000/tcp quirky_sinoussi ``` ### kitematic安裝 https://github.com/docker/kitematic/releases Kitematic 目前在 [Github](https://github.com/docker/kitematic) 上開源,而它也早在 2015 年就已經被 Docker 收購,現在集成在docker desktop Kitematic 完全自動化了 Docker 安裝和設置過程,并提供了一個直觀的圖形用戶接口(GUI)來運行 Docker。 通過 GUI 你可以非常容易的創建、運行和管理你的容器,不需要使用命令行或者是在 Docker CLI 和 GUI之間來回切換; 同時也可以方便的修改環境變量、查看日志以及配置數據卷等。 https://github.com/docker/kitematic/releases/download/v0.17.13/Kitematic-0.17.13-Mac.zip 安裝后打開,輸入docker的用戶名密碼登錄或者點擊右下角的 Skip For Now 忽略登錄 卸載: **Mac** - Remove Kitematic.app - Remove any unwanted Virtual Machines in VirtualBox ```bash # remove app data rm -rf ~/Library/Application\ Support/Kitematic ``` **Windows** Open `Programs and Features` from `Control Panel` - Uninstall Kitematic - Uninstall Oracle VM VirtualBox ## Docker鏡像詳解 ### 1、什么是鏡像 鏡像是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基于運行環境開發的軟件,它包含運行某個軟件所需要的所有內容,包括代碼,運行時(一個程序在運行或者在被執行的依賴)、庫,環境變量和配置文件。 ### 2、UnionFS(聯合文件系統) **UnionFS(聯合文件系統)**:是一種分層、輕量級并且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。 Union 文件系統是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基于基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像 **特性:**一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄 ### 3、bootfs與rootfs **bootfs(boot fle system)**:主要包含bootloader和kernel, bootloader主要是引導加載kernel.Linux剛啟動時會加載bootfs文件系統,在Docker鏡像的最底層是bootfs。這一層與我們典型的LinuxUnix系統是一樣的,包含boot加載器和內核。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs。 **rootfs (root fle system)**,在boots之上。包含的就是典型Linux系統中的ldev,lproc,/bin, letc等標準目錄和文件。rootfs就是各種不同的操作系統發行版,比如Ubuntu,Centos等等。 <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/466dae85e94640f293956b9d6f386792.png" alt="466dae85e94640f293956b9d6f386792" style="zoom:70%;" /> ### 4、Docker鏡像加載原理 <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/WechatIMG162.png" alt="WechatIMG162" style="zoom:50%;" /> ### 5、Docker鏡像分層理解 Docker的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統是UnionFS聯合文件系統。它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下。 ![20210718123512798](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/20210718123512798.png) ```bash [root@bothtech 1]# docker image inspect nginx:1.20.2 [ { "Id": "sha256:50fe74b50e0d0258922495297efbb9ebc3cbd5742103df1ca54dc21c07d24575", "RepoTags": [ "nginx:1.20.2" ], "RepoDigests": [ "nginx@sha256:03f3cb0afb7bd5c76e01bfec0ce08803c495348dccce37bcb82c347b4853c00b" ], "Parent": "", "Comment": "", "Created": "2021-12-21T03:02:00.73193624Z", "Container": "99fb95d2e2aeeee02f02da7b80d3e5f9b17b39dd77396c0ada20cf398413959a", "ContainerConfig": { "Hostname": "99fb95d2e2ae", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "80/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.20.2", "NJS_VERSION=0.7.0", "PKG_RELEASE=1~bullseye" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"nginx\" \"-g\" \"daemon off;\"]" ], "Image": "sha256:df26cc3cb2d247e6a3fde577d02fe0c79843535f5824deb0d460ae15b53e730b", "Volumes": null, "WorkingDir": "", "Entrypoint": [ "/docker-entrypoint.sh" ], "OnBuild": null, "Labels": { "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>" }, "StopSignal": "SIGQUIT" }, "DockerVersion": "20.10.7", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "80/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.20.2", "NJS_VERSION=0.7.0", "PKG_RELEASE=1~bullseye" ], "Cmd": [ "nginx", "-g", "daemon off;" ], "Image": "sha256:df26cc3cb2d247e6a3fde577d02fe0c79843535f5824deb0d460ae15b53e730b", "Volumes": null, "WorkingDir": "", "Entrypoint": [ "/docker-entrypoint.sh" ], "OnBuild": null, "Labels": { "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>" }, "StopSignal": "SIGQUIT" }, "Architecture": "amd64", "Os": "linux", "Size": 141447928, "VirtualSize": 141447928, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/3c9bf8c2b9600c9a1db12cfe9a5cc164c31c68ea814e5052b2c44bdf22de7a46/diff:/var/lib/docker/overlay2/23c279c89aac85ce2f68743c76967f74bb6f29cbe40bcf82b09e96709b30f181/diff:/var/lib/docker/overlay2/c6e434601be4f9e875b87307139101e3a60927e1aff85f556c6a57f9e1ad474e/diff:/var/lib/docker/overlay2/bd3aadbe838682052d7e9d743869362018ce9e1fe2dfd480fcc377a8d6213272/diff:/var/lib/docker/overlay2/47e21691ccef3d7aceae068e199220fb5b30323a412f8366374dc32088e92a91/diff", "MergedDir": "/var/lib/docker/overlay2/59fb3ffeb5199c79987e122748d9066dda0a9dfdc93434f70507b416c6bc6dcb/merged", "UpperDir": "/var/lib/docker/overlay2/59fb3ffeb5199c79987e122748d9066dda0a9dfdc93434f70507b416c6bc6dcb/diff", "WorkDir": "/var/lib/docker/overlay2/59fb3ffeb5199c79987e122748d9066dda0a9dfdc93434f70507b416c6bc6dcb/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f", "sha256:9ccbab2746b88b2992bfff96811aad769d8dc6f272077d19d7a831de859d9dc7", "sha256:108a6d6c3e60d60490f41cd8c1866a9fda99f79448742970b4b8aa7f7e1cd46f", "sha256:35437a3771fcd62ec7661c439d3df698699fd1229d220fbec8f330f2df5616e1", "sha256:4e498ce5ae6a4ff9a644958303b5cc140a99831025883173ebb3ae7d00b98500", "sha256:c75c795b7d446c20af2827f10f55804b93fba2a319444e297a2951261ae14fc1" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ] ``` 這里顯示分層信息: <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220313143932574.png" alt="image-20220313143932574" style="zoom:50%;" /> ![20210718123636415](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/20210718123636415.png) ![2021071812372978](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/2021071812372978.png) ![2021071812374035](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/2021071812374035.png) - Docker鏡像都是只讀的 - 當容器啟動時,一個新的可寫層被加載到鏡像的頂部 - 這一層通常被稱作“容器層”,“容器層”之下的都叫“鏡像層” - ### 6、提交鏡像 ```bash 使用docker commit 命令提交容器成為一個新的版本 docker commit -m=“提交的描述信息” -a="作者" 容器id 目標鏡像名:[TAG] ``` 由于默認的Tomcat鏡像的webapps文件夾中沒有任何內容,需要從webapps.dist中拷貝文件到webapps文件夾。下面自行制作鏡像:就是從webapps.dist中拷貝文件到webapps文件夾下,并提交該鏡像作為一個新的鏡像。使得該鏡像默認的webapps文件夾下就有文件。具體命令如下: ```bash #1.復制文件夾 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it tomcat /bin/bash root@2a3bf3eaa2e4:/usr/local/tomcat# cd webapps root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# ls root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# cd ../ root@2a3bf3eaa2e4:/usr/local/tomcat# cp -r webapps.dist/* webapps root@2a3bf3eaa2e4:/usr/local/tomcat# cd webapps root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2a3bf3eaa2e4 tomcat "/bin/bash" 4 minutes ago Up 4 minutes 8080/tcp competent_torvalds 7789d4505a00 portainer/portainer "/portainer" 24 hours ago Up 24 hours 0.0.0.0:8088->9000/tcp quirky_sinoussi [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it 2a3bf3eaa2e4 /bin/bash root@2a3bf3eaa2e4:/usr/local/tomcat# cd webapps root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2a3bf3eaa2e4 tomcat "/bin/bash" 8 minutes ago Up 8 minutes 8080/tcp competent_torvalds 7789d4505a00 portainer/portainer "/portainer" 24 hours ago Up 24 hours 0.0.0.0:8088->9000/tcp quirky_sinoussi #2.提交鏡像作為一個新的鏡像 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker commit -m="add webapps" -a="Ethan" 2a3bf3eaa2e4 mytomcat:1.0 sha256:f189aac861de51087af5bc88a5f1de02d9574e7ee2d163c647dd7503a2d3982b [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat 1.0 f189aac861de 7 seconds ago 653MB mysql 5.7 f07dfa83b528 6 days ago 448MB tomcat latest feba8d001e3f 10 days ago 649MB nginx latest ae2feff98a0c 12 days ago 133MB centos latest 300e315adb2f 2 weeks ago 209MB portainer/portainer latest 62771b0b9b09 5 months ago 79.1MB elasticsearch 7.6.2 f29a1ee41030 9 months ago 791MB #3.運行容器 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it mytomcat:1.0 /bin/bash root@1645774d4605:/usr/local/tomcat# cd webapps root@1645774d4605:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager ``` ## 創建Docker容器 ### 1、創建nginx容器 ```bash mkdir -p /data/nginx/{html,conf/conf.d,logs} docker pull nginx:1.20.2 docker run -d -p 8081:80 --name cpnginx nginx:1.20.2 docker cp cpnginx:/etc/nginx/nginx.conf /data/nginx/conf/ docker stop `docker ps -qaf 'name=cpnginx'` docker rm `docker ps -qaf 'name=cpnginx'` docker run -d -p 8081:80 --name mynginx -v /data/nginx/html:/usr/share/nginx/html -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /data/nginx/conf/conf.d:/etc/nginx/conf.d -v /data/nginx/logs:/var/log/nginx nginx:1.20.2 ``` ### 2、創建tomcat容器 ```bash [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker pull tomcat Using default tag: latest latest: Pulling from library/tomcat 6c33745f49b4: Pull complete ef072fc32a84: Pull complete c0afb8e68e0b: Pull complete d599c07d28e6: Pull complete e8a829023b97: Pull complete d04be46a31d1: Pull complete db6007c69c35: Pull complete e4ad4c894bce: Pull complete 248895fda357: Pull complete 277059b4cba2: Pull complete Digest: sha256:57dae7dfb9b62a413cde65334c8a18893795cac70afc3be589c8336d8244655d Status: Downloaded newer image for tomcat:latest docker.io/library/tomcat:latest [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -p 3335:8080 --name tomcat01 tomcat 7136295a6082cb0f805b025a1471bde02ead4864be3e2c9dcd337b1dde0a3113 ``` ### 3、創建mysql容器 ```bash mkdir -p /data/mysql/{data,conf,logs} docker run -d --name mysql5737 -p 3306:3306 -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/data:/var/lib/mysql -v /data/mysql/logs:/var/log/mysql -e MYSQL_ROOT_PASSWORD=johnny1314 mysql:5.7.37 “數據庫未初始化,密碼沒設置。你需要設置MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD三個中的任意一項” 其中 MYSQL_ROOT_PASSWORD即root賬戶的密碼。 MYSQL_ALLOW_EMPTY_PASSWORD即允許密碼為空。 MYSQL_RANDOM_ROOT_PASSWORD隨機一個root賬戶密碼。 ``` ### 4、創建php容器 在使用nginx的時候必須先啟動php容器,啟動php容器后可以把php容器網絡加入到nginx中,啟動php時候可以不做9000端口映射 ```bash docker run -d --name php-web -p 9000:9000 -v /data/nginx/html:/www php:7.4.28 ``` php安裝擴展: ```bash docker-php-ext-install 擴展名稱 docker-php-ext-install pdo_mysql ``` 時區: ```bash cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ``` ### 5、創建ElasticSearch容器 添加 ’-e ES_JAVA_OPTS="-Xms128m -Xmx512m" ‘ 配置ElasticSearch的虛擬機占用的內存大小。 docker stats 查看資源占用情況 ```bash docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2 3b8cd4991814896c523ee67b84ce198e32bd82b1a62d512b198138a58ca946f1 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3b8cd4991814 elasticsearch:7.6.2 "/usr/local/bin/dock…" 10 seconds ago Up 6 seconds 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch01 [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker stats ``` ## 容器數據卷 ### 1、數據卷介紹 Docker將運用與運行的環境打包形成容器運行, Docker容器產生的數據,如果不通過docker commit生成新的鏡像,使得數據做為鏡像的一部分保存下來, 那么當容器刪除后,數據自然也就沒有了。 為了能保存數據在Docker中我們使用卷。| 卷就是目錄或文件,存在于一個或多個容器中,由Docker掛載到容器,但卷不屬于聯合文件系統(Union FileSystem),因此能夠繞過聯合文件系統提供一些用于持續存儲或共享數據的特性: 卷的設計目的就是數據的持久化,完全獨立于容器的生存周期,因此Docker不會在容器刪除時刪除其掛載的數據卷。 數據卷的特點: 數據卷可在容器之間共享或重用數據 卷中的更改可以直接生效 數據卷中的更改不會包含在鏡像的更新中 數據卷的生命周期一直持續到沒有容器使用它為止 ### 2、簡單使用 運行容器,指定掛在數據卷命令: ``` docker run -it -v 主機目錄:容器目錄 如果沒有目錄,會自動創建 ``` 宿主機目錄/tmp/test與容器/home建立數據卷,首先在容器目錄下創建test.sh文件,再去宿主機目錄下查看是否有該文件。 <img src="https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326201747592.png" alt="image-20220326201747592" /> ![](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326201825328.png) 查看容器對應元數據`docker inspect 容器id`,可以在Mounts節點查看建立的數據卷信息。 ![image-20220326202124402](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326202124402.png) 即使容器停止運行或者容器刪除,仍然可以實現數據同步,本地的數據卷不會丟失。 ### 3. MySQL容器建立數據卷同步數據 在Linux下的MySQL默認的數據文檔存儲目錄為/var/lib/mysql,默認的配置文件位置/etc/mysql/conf.d,為了確保MySQL鏡像或容器刪除后,造成的數據丟失,下面建立數據卷保存MySQL的數據和文件。 ```java docker run -d -p 6603:3306 -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7.37 ``` 如果使用配置的密碼連接mysql服務失敗,原因很大可能是本機掛載的配置文件中已有文件,將容器中的配置給覆蓋了,我們將相應的本機文件中的文件配置刪除即可. ### 4. 常用命令 (1)創建數據卷 ```java docker volume create my-vol ``` (2)查看所有的數據卷 ```java docker volume ls local my-vol ``` (3)查看指定數據卷的信息 ```java docker volume inspect my-vol [ { "CreatedAt": "2022-03-26T20:33:27+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/my-vol/_data", "Name": "my-vol", "Options": {}, "Scope": "local" } ] ``` (4)刪除數據卷 `docker volume rm ...` ```java docker volume rm my-vol ``` (5)刪除容器之時刪除相關的卷 ```java docker rm -f -v 容器id ``` **創建容器時指定宿主機映射目錄的數據卷不會被刪除,而沒有指定的數據卷會被刪除** 無主的數據卷可能會占據很多空間,要清理請使用以下命令 ```java docker volume prune ``` ### 5、volume與mount的總結 用戶能夠經過`docker run`的`--volume/-v`或`--mount`選項來建立帶有數據卷的容器 命令用法 `--volume(-v)` 參數`--volume`(或簡寫為`-v`)只能建立bind mount。示例: ```java docker run --name $CONTAINER_NAME -it \ -v $PWD/$CONTAINER_NAME/app:/app:rw \ -v $PWD/$CONTAINER_NAME/data:/data:ro \ avocado-cloud:latest /bin/bash ``` 注釋: - 命令格式:`[[HOST-DIR:]CONTAINER-DIR[:OPTIONS]]]` - 若是指定`HOST-DIR`則必須是絕對路徑,若是路徑不存在則會自動建立 - 實例中的`rw`為讀寫,`ro`為只讀 `--mount` 參數`--mount`默認狀況下用來掛載volume,但也能夠用來建立bind mount和tmpfs。若是不指定`type`選項,則默認為掛載volume,volume是一種更為靈活的數據管理方式,volume能夠經過`docker volume`命令集被管理。示例: ```java docker run --name $CONTAINER_NAME -it \ --mount type=bind,source=$PWD/$CONTAINER_NAME/app,destination=/app \ --mount source=${CONTAINER_NAME}-data,destination=/data,readonly \ avocado-cloud:latest /bin/bash ``` 注釋: - 掛載volume命令格式:`[type=volume,]source=my-volume,destination=/path/in/container[,...]` - 建立bind mount命令格式:`type=bind,source=/path/on/host,destination=/path/in/container[,...]` - 若是建立bind mount并指定`source`則必須是絕對路徑,**且路徑必須已經存在** - 示例中`readonly`表示只讀 差別總結 建立bind mount和掛載volume的比較 | 對比項 | bind mount | volume | | :----------- | :---------------- | :----------------------- | | Source位置 | 用戶指定 | /var/lib/docker/volumes/ | | Source為空 | 覆蓋dest為空 | 保留dest內容 | | Source非空 | 覆蓋dest內容 | 覆蓋dest內容 | | Source種類 | 文件或目錄 | 只能是目錄 | | 可移植性 | 通常(自行維護) | 強(docker托管) | | 宿主直接訪問 | 容易(僅需chown) | 受限(需登錄root用戶)* | *注釋:Docker沒法簡單地經過`sudo chown someuser: -R /var/lib/docker/volumes/somevolume`來將volume的內容開放給主機上的普通用戶訪問,若是開放更多權限則有安全風險。而這點上Podman的設計就要理想得多,volume存放在`$HOME/.local/share/containers/storage/volumes/`路徑下,即提供了便捷性,又保障了安全性。無需root權限便可運行容器,這正是Podman的優點之一,實際使用過程當中的確受益良多。i 建立bind mount時使用`--volume`和`--mount`的比較 | 對比項 | `--volume` 或 `-v` | `--mount type=bind` | | :----------------: | :----------------- | :------------------ | | 若是主機路徑不存在 | 自動建立 | 命令報錯 | ### 6、具名掛載和匿名掛載 #### 1、匿名掛載 匿名掛載就是在指定數據卷的時候,不指定容器路徑對應的主機路徑,這樣對應映射的主機路徑就是默認的路徑/var/lib/docker/volumes/中自動生成一個隨機命名的文件夾。 ```java root@mycentos7 /$ docker run -d -P --name nginx01 -v /etc/nginx nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx a2abf6c4d29d: Pull complete a9edb18cadd1: Pull complete 589b7251471a: Pull complete 186b1aaa4aa6: Pull complete b4df32aa5a72: Pull complete a0bcbecc962e: Pull complete Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31 Status: Downloaded newer image for nginx:latest ad1fc76b3fb2407ffd35649d38354346bb2c122a1fce32ef46982ed2158eb9da root@mycentos7 /$ docker volume ls DRIVER VOLUME NAME local 2b83245656b2acbacd9085e22c2d3dff1edd7b65bb087f9fc586d44f337b2f5d root@mycentos7 /$ docker inspect nginx01 | grep 2b83245656b2acbacd9085e22c2d3dff1edd7b65bb087f9fc586d44f337b2f5d "Name": "2b83245656b2acbacd9085e22c2d3dff1edd7b65bb087f9fc586d44f337b2f5d", "Source": "/var/lib/docker/volumes/2b83245656b2acbacd9085e22c2d3dff1edd7b65bb087f9fc586d44f337b2f5d/_data", ``` #### 2、具名掛載 具名掛載,就是指定文件夾名稱,區別于指定路徑掛載,這里的指定文件夾名稱是在Docker指定的默認數據卷路徑下的。通過`docker volume ls`命令可以查看當前數據卷的目錄情況。 ```java root@mycentos7 /$ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx 2d1e751e538a8b2e4ab3348bff248227cc046438624a7033ee37f090ece83a0c root@mycentos7 /$ docker volume ls DRIVER VOLUME NAME local 2b83245656b2acbacd9085e22c2d3dff1edd7b65bb087f9fc586d44f337b2f5d local juming-nginx root@mycentos7 /$ docker inspect nginx02 | grep juming-nginx "juming-nginx:/etc/nginx" "Name": "juming-nginx", "Source": "/var/lib/docker/volumes/juming-nginx/_data", ``` 查看指定的數據卷信息的命令:`docker volume inspect數據卷名稱` ```java root@mycentos7 /$ docker volume inspect juming-nginx [ { "CreatedAt": "2022-03-26T22:06:15+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", "Name": "juming-nginx", "Options": null, "Scope": "local" } ] ``` 可以看到主機數據卷掛載在/var/lib/docker/volumes/juming-nginx/_data上 Docker所有的數據卷默認在/var/lib/docker/volumes/ 目錄下 匿名掛載,具名掛載,指定路徑掛載的命令區別如下: -v 容器內路徑 #匿名掛載 -v 卷名:容器內路徑 #具名掛載 -v /宿主機路徑:容器內路徑 #指定路徑掛載 指定數據卷映射的相關參數: ro —— readonly 只讀。設置了只讀則只能操作宿主機的路徑,不能操作容器中的對應路徑。 rw —— readwrite 可讀可寫 ```java # docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx # docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx ``` ### 7、Dockerfile中設置數據卷 我們可以在Dockerfile中使用VOLUME指令來給鏡像添加一個或多個數據卷。 下面使用Dockerfile構建一個新的鏡像,dockerfile01文件的內容,匿名掛載了volume01和volume02兩個目錄: vim /data/dockerfile01 ```java FROM centos VOLUME ["volume01","volume02"] CMD echo "----end----" CMD /bin/bash ``` 執行構建鏡像 ```java root@mycentos7 /data$ docker build -f /data/dockerfile01 -t grrrrlj/centos:1.0 . Sending build context to Docker daemon 219.9MB Step 1/4 : FROM centos ---> 5d0da3dc9764 Step 2/4 : VOLUME ["volume01","volume02"] ---> Using cache ---> 3939acadface Step 3/4 : CMD echo "----end----" ---> Using cache ---> 8d4bb48829c8 Step 4/4 : CMD /bin/bash ---> Using cache ---> a0a920b6fb02 Successfully built a0a920b6fb02 Successfully tagged grrrrlj/centos:1.0 root@mycentos7 /data$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ethan/centos 1.0 a0a920b6fb02 55 seconds ago 231MB grrrrlj/centos 1.0 a0a920b6fb02 55 seconds ago 231MB mysql 5.7.37 05311a87aeb4 8 days ago 450MB hwdsl2/ipsec-vpn-server latest f19f5bbe6abd 2 months ago 44MB nginx latest 605c77e624dd 2 months ago 141MB hello-world latest feb5d9fea6a5 6 months ago 13.3kB centos latest 5d0da3dc9764 6 months ago 231MB ``` 完成鏡像的生成后,啟動自己生成的容器 ```java root@mycentos7 /data$ docker run -it a0a920b6fb02 /bin/bash [root@cbf58bdb178c /]# ls -l total 4 lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x 5 root root 360 Mar 26 14:20 dev drwxr-xr-x 1 root root 66 Mar 26 14:20 etc drwxr-xr-x 2 root root 6 Nov 3 2020 home lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64 drwx------ 2 root root 6 Sep 15 2021 lost+found drwxr-xr-x 2 root root 6 Nov 3 2020 media drwxr-xr-x 2 root root 6 Nov 3 2020 mnt drwxr-xr-x 2 root root 6 Nov 3 2020 opt dr-xr-xr-x 172 root root 0 Mar 26 14:20 proc dr-xr-x--- 2 root root 162 Sep 15 2021 root drwxr-xr-x 11 root root 163 Sep 15 2021 run lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x 2 root root 6 Nov 3 2020 srv dr-xr-xr-x 13 root root 0 Mar 26 14:20 sys drwxrwxrwt 7 root root 171 Sep 15 2021 tmp drwxr-xr-x 12 root root 144 Sep 15 2021 usr drwxr-xr-x 20 root root 4096 Sep 15 2021 var drwxr-xr-x 2 root root 6 Mar 26 14:20 volume01 drwxr-xr-x 2 root root 6 Mar 26 14:20 volume02 ``` 可以看到自動掛載的數據卷目錄。下面查看對應宿主機的數據卷目錄 ```java root@mycentos7 ~$ docker ps 127 ? CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 40549a6e8b0f a0a920b6fb02 "/bin/bash" 38 seconds ago Up 37 seconds vibrant_proskuriakova 2d1e751e538a nginx "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:49154->80/tcp, :::49154->80/tcp nginx02 ad1fc76b3fb2 nginx "/docker-entrypoint.…" 20 minutes ago Up 20 minutes 0.0.0.0:49153->80/tcp, :::49153->80/tcp nginx01 root@mycentos7 ~$ docker inspect 40549a6e8b0f "Mounts": [ { "Type": "volume", "Name": "432081a42ca914349960a69467147a8063c52e82af6ce6803efa138397e9d87d", "Source": "/var/lib/docker/volumes/432081a42ca914349960a69467147a8063c52e82af6ce6803efa138397e9d87d/_data", "Destination": "volume02", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "ebad18b53c195a0dfdcacf900ddc37fd0094a681201135a09b1f96868d96da2c", "Source": "/var/lib/docker/volumes/ebad18b53c195a0dfdcacf900ddc37fd0094a681201135a09b1f96868d96da2c/_data", "Destination": "volume01", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], ``` 可以看到Mounts下有宿主機的掛載目錄。因為dockerfile中沒有指定宿主機目錄,所以屬于匿名掛載,在/var/lib/docker/volumes/目錄下生成了隨機命名的路徑。 ### 8、 容器數據卷 容器數據卷是指建立數據卷,來同步多個容器間的數據,實現容器間的數據同步。 父子容器數據卷的內容實時同步。 首先啟動容器1,volume01、volume02為掛載目錄。 ```java [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it --name centos01 grrrrlj/centos:1.0 [root@731d53b8c3d5 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02 ``` 然后啟動容器2,通過參數`--volumes-from`,設置容器2和容器1建立數據卷掛載關系。 ```java [root@iZwz99sm8v95sckz8bd2c4Z /]# docker run -it --name centos02 --volumes-from centos01 grrrrlj/centos:1.0 [root@7f90d4147511 /]# ls -l total 56 lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 360 Dec 30 14:58 dev drwxr-xr-x 1 root root 4096 Dec 30 14:58 etc drwxr-xr-x 2 root root 4096 Nov 3 15:22 home lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64 drwx------ 2 root root 4096 Dec 4 17:37 lost+found drwxr-xr-x 2 root root 4096 Nov 3 15:22 media drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt dr-xr-xr-x 108 root root 0 Dec 30 14:58 proc dr-xr-x--- 2 root root 4096 Dec 4 17:37 root drwxr-xr-x 11 root root 4096 Dec 4 17:37 run lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv dr-xr-xr-x 13 root root 0 Dec 29 15:41 sys drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr drwxr-xr-x 20 root root 4096 Dec 4 17:37 var drwxr-xr-x 2 root root 4096 Dec 30 14:54 volume01 drwxr-xr-x 2 root root 4096 Dec 30 14:54 volume02 ``` 首先在容器2中的volume01中添加文件,然后就可以看到容器1的文件也會添加上了 下面同步兩個MySQL的數據庫和配置文件,與上面的操作相同,首先建立數據卷,然后給另一個MySQL容器建立容器數據卷掛載,示例: ```java [root@iZwz99sm8v95sckz8bd2c4Z home]# docker run -d -p 6603:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 [root@iZwz99sm8v95sckz8bd2c4Z home]# docker run -d -p 6604:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7 ``` ## Dockerfile ### 1、Dockerfile介紹 Dockerfile是用來構建Docker鏡像的文本文件,也可以說是命令參數腳本。docker build命令用于從Dockerfile構建鏡像。可以在docker build命令中使用-f標志指向文件系統中任何位置的Dockerfile。 Docker鏡像發布的步驟: 1、編寫一個dockerfile文件 2、docker build 構建成為一個鏡像 3、docker run 鏡像 4、docker push 鏡像(發布鏡像到DockerHub、阿里云鏡像倉庫) 示例一個鏡像的結構圖: ![image-20220326232012442](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326232012442.png) ### 2、Dockerfile指令說明 | 指令 | 說明 | | ---------- | ------------------------------------------------------------ | | FROM | 指定基礎鏡像 | | MAINTAINER | 鏡像是誰寫的,姓名+郵箱 | | RUN | 鏡像構建的時候需要運行的命令 | | ADD | 將本地文件添加到容器中,tar類型文件會自動解壓(網絡壓縮資源不會被解壓),可以訪問網絡資源,類似wget | | WORKDIR | 鏡像的工作目錄 | | VOLUME | 掛載的目錄 | | EXPOSE | 保留端口配置 | | CMD | 指定這個容器啟動的時候要運行的命令(只有最后一個會生效) | | EMTRYPOINT | 指定這個容器啟動的時候要運行的命令,可以追加命令 | | ONBUILD | 當構建一個被繼承DockerFile,這個時候就會運行ONBUILD的指令,觸發指令 | | COPY | 功能類似ADD,但是是不會自動解壓文件,也不能訪問網絡資源 | | ENV | 構建的時候設置環境變量 | 一個形象的解釋各個指令作用的圖: ![image-20220326232257951](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326232257951.png) Dockerfile 一般分為四部分:基礎鏡像信息、維護者信息、鏡像操作指令和容器啟動時執行指令,’#’ 為 Dockerfile 中的注釋。 關于DockerFile文件的腳本注意點有: 1、每個保留關鍵字(指令)都必須是大寫字母 2、文件中的指令從上到下順序執行,第一個指令必須是FROM 3、# 號表示注釋 4、每一個指令都會創建提交一個新的鏡像層,并提交! 關于Dockerfile指令的詳細語法解釋:Dockerfile文件詳解 Dockerfile指令介紹的官方文檔:https://docs.docker.com/engine/reference/builder/ ### 3. 制作Centos鏡像 下面通過編寫Dockerfile文件來制作Centos鏡像,并在官方鏡像的基礎上添加vim和net-tools工具。首先在/home/dockfile 目錄下新建文件mydockerfile-centos。然后使用上述指令編寫該文件。 ```java [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# cat mydockerfile-centos FROM centos MAINTAINER ethan<1258398543@qq.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "---end---" CMD /bin/bash ``` 逐行解釋該Dockerfile文件的指令: FROM centos:該image文件繼承官方的centos,后面加冒號如centos:7,用于指定鏡像的版本 ENV MYPATH /usr/local:設置環境變量MYPATH ,后面有用到 WORKDIR $MYPATH:直接使用上面設置的環境變量,指定/usr/local為工作目錄 RUN yum -y install vim和RUN yum -y install net-tools:在/usr/local目錄下,運行yum -y install vim和yum -y install net-tools命令安裝工具,注意安裝后的所有依賴和工具都會打包到image文件中 EXPOSE 80:將容器80端口暴露出來,允許外部連接這個端口 CMD:指定容器啟動的時候運行命令 通過這個dockerfile構建鏡像,構建鏡像命令:docker build -f dockerfile文件路徑 -t 鏡像名[:版本號] .(這里有個小點.) 上面命令中,-t參數用來指定 image 文件的名字,后面還可以用冒號指定標簽。如果不指定,默認的標簽就是latest。最后的那個點表示 Dockerfile 文件所在的路徑,上例是當前路徑,所以是一個點。 下面執行build命令生成image文件,如果執行成功,可以通過docker images來查看新生成的鏡像文件。 ```java [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/10 : FROM centos ---> 300e315adb2f Step 2/10 : MAINTAINER ethan<1258398543@qq.com> ---> Running in bbfd1a4949e1 Removing intermediate container bbfd1a4949e1 ---> b2b6851e55fa Step 3/10 : ENV MYPATH /usr/local ---> Running in 7cd8c84a5b70 Removing intermediate container 7cd8c84a5b70 ---> e27a56b5247b Step 4/10 : WORKDIR ${MYPATH} ---> Running in 770e175260c4 Removing intermediate container 770e175260c4 ---> 7d46880ef0fd Step 5/10 : RUN yum -y install vim Step 7/10 : EXPOSE 80 ---> Running in 24cfcfa56460 Removing intermediate container 24cfcfa56460 ---> 2064c1540e8e Step 8/10 : CMD echo ${MYPATH} ---> Running in 83dd9766da3c Removing intermediate container 83dd9766da3c ---> 9b8661c812c4 Step 9/10 : CMD echo "---end---" ---> Running in 974afa805b27 Removing intermediate container 974afa805b27 ---> 83459c404586 Step 10/10 : CMD /bin/bash ---> Running in 4fba3174f9d8 Removing intermediate container 4fba3174f9d8 ---> 1185a46e3a12 Successfully built 1185a46e3a12 Successfully tagged mycentos:1.0 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mycentos 1.0 1185a46e3a12 4 minutes ago 291MB ``` 下面生成容器,測試相關命令,查看默認工作目錄是否設置成功,vim和net-tools工具是否下載成功。 ```java [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run -it mycentos:1.0 [root@e548efe82b30 local]# pwd /usr/local #net-tools工具提供ifconfig命令 [root@e548efe82b30 local]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@e548efe82b30 local]# vi test.txt [root@e548efe82b30 local]# cat test.txt Hello world! ``` 另外,我們通過`docker history 容器id`命令來查看鏡像的構建步驟 ```java [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker history 1185a46e3a12 IMAGE CREATED CREATED BY SIZE COMMENT 1185a46e3a12 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B 83459c404586 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 9b8661c812c4 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 2064c1540e8e 13 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B 1b15d4a1fd5e 13 minutes ago /bin/sh -c yum -y install net-tools 23.3MB 9336c20f0b6d 13 minutes ago /bin/sh -c yum -y install vim 58MB 7d46880ef0fd 14 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B e27a56b5247b 14 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B b2b6851e55fa 14 minutes ago /bin/sh -c #(nop) MAINTAINER ethan<12583985… 0B 300e315adb2f 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 3 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 3 weeks ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB ``` ### 4、RUN,CMD和ENTRYPOINT的區別 簡單說,RUN命令在 image 文件的構建階段執行,執行結果都會打包進入 image 文件;CMD命令則是在容器啟動后執行。另外,一個 Dockerfile 可以包含多個RUN命令,但是只能有一個CMD命令。 注意,指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否則它會覆蓋CMD命令。 CMD和ENTRYPOINT的區別在哪里? CMD :指定容器啟動的時候要運行的命令,只有最后一個會生效 ENTRYPOINT :指定容器啟動的時候要運行的命令,命令可以追加 首先是使用CMD指令 ```java [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# cat dockerfile-cmd-test FROM centos CMD ["ls","-a"] [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 . Sending build context to Docker daemon 3.072kB Step 1/2 : FROM centos ---> 300e315adb2f Step 2/2 : CMD ["ls","-a"] ---> Running in 6d4d0112322f Removing intermediate container 6d4d0112322f ---> b6ec5224d2ac Successfully built b6ec5224d2ac Successfully tagged cmdtest:1.0 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:1.0 . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var #由于使用的是 CMD指令,命令無追加,-l取代了原本的ls -a,而-l命令不存在所以報錯。 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:1.0 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown. ``` 可以看到追加命令-l 出現了報錯。 下面使用ENTRYPOINT來構建一個鏡像 ```java #1.修改dockerfile文件 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# cat dockerfile-cmd-test FROM centos ENTRYPOINT ["ls","-a"] #2.構建鏡像 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:2.0 . Sending build context to Docker daemon 3.072kB Step 1/2 : FROM centos ---> 300e315adb2f Step 2/2 : ENTRYPOINT ["ls","-a"] ---> Running in 61389c0c1967 Removing intermediate container 61389c0c1967 ---> ac7b7e83ff88 Successfully built ac7b7e83ff88 Successfully tagged cmdtest:2.0 #3.運行鏡像 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:2.0 . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var #4.追加鏡像再次運行 [root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:2.0 -l total 56 drwxr-xr-x 1 root root 4096 Jan 1 03:55 . drwxr-xr-x 1 root root 4096 Jan 1 03:55 .. -rwxr-xr-x 1 root root 0 Jan 1 03:55 .dockerenv lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 340 Jan 1 03:55 dev drwxr-xr-x 1 root root 4096 Jan 1 03:55 etc drwxr-xr-x 2 root root 4096 Nov 3 15:22 home lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64 drwx------ 2 root root 4096 Dec 4 17:37 lost+found drwxr-xr-x 2 root root 4096 Nov 3 15:22 media drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt dr-xr-xr-x 106 root root 0 Jan 1 03:55 proc dr-xr-x--- 2 root root 4096 Dec 4 17:37 root drwxr-xr-x 11 root root 4096 Dec 4 17:37 run lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv dr-xr-xr-x 13 root root 0 Dec 29 15:41 sys drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr drwxr-xr-x 20 root root 4096 Dec 4 17:37 var ``` ### 5. 制作Tomcat鏡像并發布鏡像 #### 1、制作Tomcat鏡像 1.準備鏡像文件tomcat、jdk壓縮包 ```java [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# vi readme.txt [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# ll total 200700 -rw-r--r-- 1 root root 10371538 Jan 1 16:11 apache-tomcat-8.5.55.tar.gz -rw-r--r-- 1 root root 195132576 Jan 1 16:13 jdk-8u251-linux-x64.tar.gz -rw-r--r-- 1 root root 20 Jan 1 16:14 readme.txt ``` 2.編寫dockerfile文件,文件名使用官方命名:Dockerfile ,build的時候會默認尋找當前目錄下的文件,不需要使用-f參數指定 ```java [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# vim Dockerfile [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# cat Dockerfile FROM centos MAINTAINER ethan<1258398543@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u251-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-8.5.55.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_251 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.55 ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.55 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-8.5.55/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.55/bin/logs/catalina.out ``` 3.使用該Dockerfile構建鏡像 ```java [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# docker build -t diytomcat:1.0 . ``` 4.啟動生成的鏡像,構建Tomcat容器. 這里設置了數據卷,宿主機的/home/dockerfile/tomcat/test對應該容器的/usr/local/apache-tomcat-8.5.55/webapps/test。這樣關于test項目的修復只需要在宿主機上修改就可以了,不需要進入到容器中修改。 ```java [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# docker run -d -p 8088:8080 --name diytomcat -v /home/dockerfile/tomcat/test:/usr/local/apache-tomcat-8.5.55/webapps/test diytomcat:1.0 ``` 5.在/home/dockerfile/tomcat/test的目錄下,新建index.html 測試Tomcat是否能正常使用。 因為設置了卷掛載所以可以直接在宿主機中進行操作。 ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>這是個標題</title> </head> <body> <h1>這是一個一個簡單的HTML</h1> <p>Hello World!</p> </body> </html> ``` 6.訪問測試,瀏覽器訪問查看是否能正常訪問 ![image-20220326234026827](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326234026827.png) 如果頁面顯示亂碼,就需要修改tomcat的server.xml文件 ```java <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" /> ``` 這里是添加了一個屬性:URIEncoding,將該屬性值設置為UTF-8,即可讓Tomcat(默認ISO-8859-1編碼)以UTF-8的編碼處理get請求。 #### 2、發布鏡像到DockerHub 1.登錄https://hub.docker.com/ DockerHub官網進行注冊 2.進行登錄,docker login -u 用戶名 登錄命令 ```java [root@iZwz99sm8v95sckz8bd2c4Z test]# docker login --help Usage: docker login [OPTIONS] [SERVER] Log in to a Docker registry. If no server is specified, the default is defined by the daemon. Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Usernames ``` 3.使用`docker push`命令推送鏡像到DockerHub上的倉庫 ```java [root@iZwz99sm8v95sckz8bd2c4Z test]# docker tag 0975df661526 ethanhuang824/diytomcat:1.0 [root@iZwz99sm8v95sckz8bd2c4Z test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE diytomcat 1.0 0975df661526 About an hour ago 688MB ethanhuang824/diytomcat 1.0 0975df661526 About an hour ago 688MB cmdtest 2.0 ac7b7e83ff88 6 hours ago 209MB cmdtest 1.0 b6ec5224d2ac 6 hours ago 209MB ethan/centos 1.0 1df90e6fd790 2 days ago 209MB mytomcat 1.0 f189aac861de 3 days ago 653MB mysql 5.7 f07dfa83b528 10 days ago 448MB tomcat latest feba8d001e3f 2 weeks ago 649MB nginx latest ae2feff98a0c 2 weeks ago 133MB centos latest 300e315adb2f 3 weeks ago 209MB elasticsearch 7.6.2 f29a1ee41030 9 months ago 791MB [root@iZwz99sm8v95sckz8bd2c4Z test]# docker push ethanhuang824/diytomcat:1.0 ``` 因為push的時候,鏡像名前面需要加上用戶名(ethanhuang824是我的用戶名。如果用戶名不是當前登錄用戶則會拒絕push請求),所以需要使用命令docker tag 鏡像名 新的鏡像名復制出一份鏡像重新打個Tag。 ### 6、發布鏡像到阿里云容器服務 1.登錄阿里云,找到容器鏡像服務 2.創建命名空間 3.上傳鏡像 ## Docker網絡 清空鏡像及容器 ### 1、Docker默認的網絡模式 使用以下命令查看所有的Docker網絡: ```java docker network ls ``` Docker默認提供了四個網絡模式,說明: bridge:容器默認的網絡是橋接模式(自己搭建的網絡默認也是使用橋接模式,啟動容器默認也是使用橋接模式)。此模式會為每一個容器分配、設置IP等,并將容器連接到一個docker0虛擬網橋,通過docker0網橋以及Iptables nat表配置與宿主機通信。 none:不配置網絡,容器有獨立的Network namespace,但并沒有對其進行任何網絡設置,如分配veth pair 和網橋連接,配置IP等。 host:容器和宿主機共享Network namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。 container:創建的容器不會創建自己的網卡,配置自己的IP容器網絡連通。容器和另外一個容器共享Network namespace(共享IP、端口范圍)。 容器默認使用bridge網絡模式,我們使用該docker run --network=選項指定容器使用的網絡: host模式:使用 --net=host 指定。 none模式:使用 --net=none 指定。 bridge模式:使用 --net=bridge 指定,默認設置。 container模式:使用 --net=container:NAME_or_ID 指定。 1.1 host模式 Namespace的簡要說明: Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等。 一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、Iptable規則等都與其他的NetworkNamespace隔離。一個Docker容器一般會分配一個獨立的Network Namespace。 如果啟動容器的時候使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。但是,容器的其他方面,如文件系統、進程列表等還是和宿主機隔離的。 使用host模式的容器可以直接使用宿主機的IP地址與外界通信,容器內部的服務端口也可以使用宿主機的端口,不需要進行NAT,host最大的優勢就是網絡性能比較好,但是docker host上已經使用的端口就不能再用了,網絡的隔離性不好。Host模式的模型圖,如下圖所示: ![image-20220326235809689](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220326235809689.png) 備注:eth0為宿主機的10.126.130.4為宿主機的內網地址。 1.2 container模式 這個模式指定新創建的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新創建的容器不會創建自己的網卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。同樣,兩個容器除了網絡方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網卡設備通信。Container模式模型示意圖如下: ![image-20220327001400976](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001400976.png) 1.3 none模式 使用none模式,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息。需要我們自己為Docker容器添加網卡、配置IP等。 這種網絡模式下容器只有lo回環網絡,沒有其他網卡。none模式可以在容器創建時通過–network=none來指定。這種類型的網絡沒有辦法聯網,封閉的網絡能很好的保證容器的安全性。 None模式示意圖: ![image-20220327001449790](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001449790.png) 1.4 bridge模式 當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。 從docker0子網中分配一個IP給容器使用,并設置docker0的IP地址為容器的默認網關。在主機上創建一對虛擬網卡veth pair設備,Docker將veth pair設備的一端放在新創建的容器中,并命名為eth0(容器的網卡),另一端放在主機中,以vethxxx這樣類似的名字命名,并將這個網絡設備加入到docker0網橋中。可以通過brctl show命令查看。 bridge模式是docker的默認網絡模式,不寫–net參數,就是bridge模式。使用docker run -p時,docker實際是在iptables做了DNAT規則,實現端口轉發功能。可以使用iptables -t nat -vnL查看。bridge模式如下圖所示: ![image-20220327001526911](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001526911.png) 當Docker server啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到這個虛擬網橋上。Docker0使用到的技術是evth-pair技術。在默認bridge網絡模式下,我們每啟動一個Docker容器,Docker就會給Docker容器配置一個ip。 Docker容器完成bridge網絡配置的過程如下: 在主機上創建一對虛擬網卡veth pair設備。veth設備總是成對出現的,它們組成了一個數據的通道,數據從一個設備進入,就會從另一個設備出來。因此,veth設備常用來連接兩個網絡設備。 Docker將veth pair設備的一端放在新創建的容器中,并命名為eth0。另一端放在主機中,以veth65f9這樣類似的名字命名,并將這個網絡設備加入到docker0網橋中。 從docker0子網中分配一個IP給容器使用,并設置docker0的IP地址為容器的默認網關。 執行命令 ip addr,可以看到安裝Docker后,默認宿主機有三個地址。 ![image-20220327001556085](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001556085.png) Docker是如何處理容器網絡訪問的呢?啟動一個容器,進入容器使用`ip addr`查看網絡設置 ```java docker run -d -P --name tomcat01 tomcat:8.0 ``` ![image-20220327001715895](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001715895.png) 可以看到容器啟動后Docker分配給容器一個格式如eth0@if262 的ip地址。宿主機運行`ip addr`命令查看變化: ![image-20220327001753100](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001753100.png) 可以看到容器內部和Linux主機都會創建一個新的網卡,而這兩個網卡都是成對的。使用的技術就是evth-pair。evth-pair 就是一對的虛擬設備接口,他們是成對出現的,一段連著協議,一段彼此相連。evth-pair充當一個橋梁,連接各種虛擬網絡設備。 ==Linux主機可以直接網絡連接Docker容器。Docker容器和容器之間同樣可以直接網絡連接的。==下面具體實驗驗證一下。 ```java docker exec -it tomcat01 ip addr ``` ![image-20220327001844055](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001844055.png) 下面再啟動一個Tomcat容器,嘗試容器之間的網絡連接是否能夠成功。 ![image-20220327001908746](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001908746.png) ![image-20220327001924145](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001924145.png) 嘗試在tomcat01容器中ping tomcat02容器,可以看到兩個容器是可以連接上的。兩個Tomcat容器之間的網絡交互模型圖如下: ![image-20220327001945783](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327001945783.png) 說明: Tomcat01和Tomcat02都使用公用的路由器docker0。所有的容器不指定網絡下,都是由docker0路由的,Docker會給我們容器默認分配一個隨機的可用IP地址。 容器網絡互聯的通用模型,如下圖所示: ![image-20220327002004973](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002004973.png) Docker中的所有的網絡接口都是虛擬的。只要容器刪除,容器對應的網橋也會刪除。 ```shell # 我們發現這個容器帶來網卡,都是一對對的 # evth-pair 就是一對的虛擬設備接口,他們都是成對出現的,一段連著協議,一段彼此相連 # 正因為有這個特性,evth-pair充當一個橋梁,連接各種虛擬網絡設備 # OpenStac,Docker容器之間的連接,OVS的連接,都是使用evth-pair技術 ``` ### 2、容器互聯 在微服務部署的場景下,注冊中心是使用服務名來唯一識別微服務的,而我們上線部署的時候微服務對應的IP地址可能會改動,所以我們需要使用容器名來配置容器間的網絡連接。使用–link可以完成這個功能。 首先不設置連接的情況下,是無法通過容器名來進行連接的。 ![image-20220327002049758](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002049758.png) 下面啟動一個Tomcat容器Tomcat03使用–link 連接已經啟動的Tomcat02容器。這樣容器Tomcat03就可以通過容器名Tomcat02連接到容器Tomcat02。 ![image-20220327002206196](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002206196.png) 但是反過來容器Tomcat02通過容器名Tomcat03直接ping容器Tomcat03是不行的。 ![image-20220327002241567](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002241567.png) 這是因為`--link`的原理是在指定運行的容器上的/etc/hosts文件中添加容器名和ip地址的映射,如下: ![image-20220327002303418](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002303418.png) 而tomcat02容器不能夠通過容器名連接tomcat03是因為tomcat02容器中并沒有添加容器名tomcat03和ip地址的映射. ![image-20220327002350811](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002350811.png) 目前–link設置容器互連的方式已經不推薦使用。因為docker0不支持容器名訪問,所以更多地選擇自定義網絡。 ### 3、自定義網絡 因為docker0,默認情況下不能通過容器名進行訪問。需要通過--link進行設置連接。這樣的操作比較麻煩,更推薦的方式是自定義網絡,容器都使用該自定義網絡,就可以實現通過容器名來互相訪問了。 下面查看network的相關命令 ```java docker network --help ``` ![image-20220327002613622](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002613622.png) 查看默認的網絡bridge的詳細信息 ![image-20220327002640082](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002640082.png) 查看 network create命令的相關參數 ![image-20220327002729446](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002729446.png) 下面自定義一個網絡: ```java docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet ``` ![image-20220327002805747](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002805747.png) 參數說明: ```java --driver bridge #指定bridge驅動程序來管理網絡 --subnet 192.168.0.0/16 #指定網段的CIDR格式的子網 --gateway 192.168.0.1 #指定主子網的IPv4或IPv6網關 ``` 網絡mynet創建成功后,查看網絡信息: ```java docker network inspect mynet ``` ![image-20220327002911235](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327002911235.png) 下面啟動兩個容器,指定使用該自定義網絡mynet,測試處于自定義網絡下的容器,是否可以直接通過容器名進行網絡訪問。 ```java docker run -d -P --name tomcat-net-01 --net mynet tomcat docker run -d -P --name tomcat-net-02 --net mynet tomcat docker network inspect mynet ``` ![image-20220327003019353](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003019353.png) 下面通過容器名來測試容器tomcat-net-01 和容器tomcat-net-02之間是否能正常網絡通信。 ![image-20220327003057995](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003057995.png) 可以發現,在我們的自定義網絡下,容器之間既可以通過容器名也可以通過ip地址進行網絡通信。 我們自定義的網絡默認已經幫我們維護了容器間的網絡通信問題,這是實現網絡互聯的推薦方式。 ### 4、Docker網絡之間的互聯 沒有設置的情況下,不同網絡間的容器是無法進行網絡連接的。如圖,兩個不同的網絡docker0和自定義網絡mynet的網絡模型圖: ![image-20220327003153990](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003153990.png) 在默認網絡bridge下啟動容器tomcat-01,嘗試連接mynet網絡下的tomcat-net-01容器。 ![image-20220327003219996](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003219996.png) 可以看到是無法網絡連接的。不同Docker網絡之間的容器需要連接的話需要把作為調用方的容器注冊一個ip到被調用方所在的網絡上。需要使用docker connect命令。 下面設置容器tomcat-01連接到mynet網絡上。并查看mynet的網絡詳情,可以看到給容器tomcat-01分配了一個ip地址。 ```java docker network connect mynet tomcat-01 ``` ![image-20220327003307967](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003307967.png) 設置完成后我們就可以實現不同網絡之間的容器互聯了。 ![image-20220327003331507](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003331507.png) ### 5. Docker網絡實戰練習 #### Redis集群部署 下面部署如圖所示的三主三從的Redis集群 ![image-20220327003352642](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003352642.png) 首先停掉所有的容器 ```java docker rm -f $(docker ps -aq) ``` ![image-20220327003431014](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003431014.png) 創建網絡名為redis的自定義網絡 ```bash docker network create redis --subnet 172.38.0.0/16 ``` ![image-20220327003449817](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003449817.png) 通過以下腳本創建六個Redis 的配置信息: ```java for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >/mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done ``` ![image-20220327003519180](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003519180-20220327004505624.png) 下面啟動6個Redis容器,設置對應的容器數據卷掛載, ```java #第1個Redis容器 docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ -v /mydata/redis/node-1/data:/data \ -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf #第2個Redis容器 docker run -p 6372:6379 -p 16372:16379 --name redis-2 \ -v /mydata/redis/node-2/data:/data \ -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf #第3個Redis容器 docker run -p 6373:6379 -p 16373:16379 --name redis-3 \ -v /mydata/redis/node-3/data:/data \ -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf #第4個Redis容器 docker run -p 6374:6379 -p 16374:16379 --name redis-4 \ -v /mydata/redis/node-4/data:/data \ -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf #第5個Redis容器 docker run -p 6375:6379 -p 16375:16379 --name redis-5 \ -v /mydata/redis/node-5/data:/data \ -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf #第6個Redis容器 docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ -v /mydata/redis/node-6/data:/data \ -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf ``` 或者通過腳本一次性啟動6個Redis容器: ```java for port in $(seq 1 6); \ do docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \ -v /mydata/redis/node-${port}/data:/data \ -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \ done ``` 執行上述腳本,運行結果如下: ![image-20220327003633989](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003633989-20220327004513750.png) 下面進入到redis-1容器中創建集群 ```shell #redis默認沒有bash docker exec -it redis-1 /bin/sh #創建集群 redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1 ``` 查看集群信息 ```java redis-cli -c cluster info ``` ![image-20220327003726162](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003726162.png) 查看節點信息`cluster nodes`,可以清楚的看到Redis節點的主從關系。 ![image-20220327003756927](../../Library/Application Support/typora-user-images/image-20220327003756927.png) 測試主從復制是否生效,設置一個key,可以看到我們重定向到了Redis-3節點,處理該操作的是Redis-3節點。 ![image-20220327003822952](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003822952.png) 新建一個會話,停止Redis-3容器服務,此時重新連接Redis-cli客戶端,再次獲取k1,重定向到了Redis-3節點的從節點Redis-4中處理。 ![image-20220327003849192](https://uppics-1256206735.cos.ap-beijing.myqcloud.com/uppics/image-20220327003849192.png) ## Docker Compose 簡介: Docker Compose 輕松高效的管理容器。定義運行多個容器。 官方介紹: 定義、運行多個容器 yaml file 配置文件 single command。命令有哪些? Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features. 所有的環境都可以使用Compose Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases. Using Compose is basically a three-step process: Define your app’s environment with a Dockerfile so it can be reproduced anywhere. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment. Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary. 三步驟: 1、Docker保證我們的項目可以運行在任何地方 2、services什么是服務。docker-compose.yml這個文件怎么寫 3、啟動項目 作用:批量容器編排。 理解: compose是docker官方的開源項目。需要安裝! dockerfile讓程序在任何地方運行。web服務\redis\mysql\nginx…多個容器 ## Docker Swarm ## CI/CD之Jenkins
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看