从零开始学Docker(超详细讲解+案例分析)
參考狂神說Docker:https://www.bilibili.com/video/BV1og4y1q7M4?p=40
目錄
- 一、Docker概述
- 1. Docker為什么出現
- 2. Docker歷史
- 3. 對比虛擬化技術
- 4. 為什么選擇Docker
- 引入Docker后:DevOps(開發、運維)
- 二、Docker安裝配置
- 1. Docker的基本組成
- 鏡像(image)
- 容器(container)
- 倉庫(repository)
- 2. 環境準備
- 3. 安裝
- 1. 卸載舊版本
- 2. 安裝Docker軟件包
- 3. 設置鏡像倉庫地址
- 4. 安裝最新版Docker Engine和容器
- 5. 啟動Docker
- 6. 運行Hello World映像測試
- 4. 卸載Docker方法
- 1. 卸載Docker依賴
- 2. 刪除Docker資源
- 5. 阿里云鏡像加速
- 三、Docker run的流程和底層原理
- 1. 流程圖
- 2. 底層原理
- Docker是怎么工作的?
- Docker為什么比VM快?
- 四、Docker常用命令
- 1. 幫助命令
- 2. 鏡像命令
- 查看所有鏡像
- 搜索鏡像
- 下載鏡像
- 刪除鏡像
- 3. 容器命令
- 新建容器并啟動
- 列出所有運行的容器
- 退出容器
- 刪除容器
- 啟動停止容器
- 4. 常用其他命令
- 后臺啟動容器
- 查看日志
- 查看容器中的進程
- 查看鏡像元數據
- 進入當前正在運行的容器
- 從容器內拷貝文件到主機
- 五、Docker命令實戰
- 1. 部署Nginx
- 2. 部署Tomcat
- 3. 部署es+kibana
- 六、Portainer可視化面板
- 1. 什么是 portainer ?
- 2. 下載
- 3. 訪問測試
- 七、Docker鏡像講解
- 1. 鏡像是什么
- 2. Docker鏡像加載原理
- 3. 分層理解
- 下載示例
- 理解
- 特點
- 4. Commit鏡像
- 八、容器數據卷
- 1. 什么是容器數據卷
- 2. 使用數據卷
- 實戰:安裝MySQL
- 3. 具名和匿名掛載
- 匿名掛載
- 具名掛載(常用)
- 拓展
- 4. 初識Dockerfile
- 5. 數據卷容器
- 九、DockerFile
- 1. DockerFile介紹
- 2. DockerFile的構建過程
- 3. DockerFile指令
- 常見指令
- CMD和ENTRYPOINT的區別
- 4. 實戰:構建自己的CentOS
- 1. 編寫dockerfile
- 2. 通過dockerfile構建鏡像
- 3. 通過鏡像啟動容器
- 5. 實戰:構建自己的Tomcat
- 1. 準備鏡像文件
- 2. 編寫dockerfile文件
- 3. 構建鏡像
- 4. 啟動容器
- 5. 進入容器
- 6. 訪問測試
- 7. 發布項目
- 6. 發布鏡像到 Docker Hub
- 1. 登錄 Docker Hub
- 2. 提交到 Docker Hub
- 7. 發布鏡像到阿里云鏡像
- 1. 創建阿里云鏡像倉庫
- 2. 提交到阿里云鏡像倉庫
- 小結
- 十、Docker網絡
- 1. Docker網絡原理
- 2. 容器互聯--link
- 3. 自定義網絡
- 4. 網絡聯通
- 實戰:部署Redis集群
- 十一、SpringBoot微服務&docker
- 1. 構建springboot項目
- 2. 打包應用
- 3. 編寫Dockerfile
- 4. 構建鏡像
- 5. 啟動容器測試
- 6. 發布鏡像
一、Docker概述
官網:https://www.docker.com/
文檔地址:https://docs.docker.com/
倉庫地址:https://hub.docker.com/
1. Docker為什么出現
一款產品的開發往往需要多套環境,比如開發環境、測試環境以及最終的上線環境;環境的配置是時分麻煩的,每一個機器都要部署環境(Redis、ES、Hadoop集群…),尤其是各種集群的部署特別浪費時間,常常會遇到 ”在我電腦上可以運行,在你電腦上不能運行“、”版本更新導致服務不用“、”不能跨平臺“ 等等大量問題,這對運維人員來說就十分棘手。
在以前,開發人員發開完成就發布一個jar或者war包,其他的都交給運維人員來做;而現在,開發即運維,打包部署上線一套流程走完:開發人員會將項目及其附帶的環境一起打包jar+(Redis Jdk ES MySQL)成一整套發布,稱為鏡像,這樣就不再需要再配置環境,直接執行一整套即可,省去環境配置的麻煩且保證了一致性;
Docker的出現就是為了解決以上問題,類似于安卓應用:
- java – apk – 發布到應用商店 – 下載即可使用
- java – jar(環境) – 打包項目+環境(鏡像) – 發布到Docker倉庫 – 下載鏡像即可直接運行
Docker 的思想來源于集裝箱,打包裝箱,每個箱子互相隔離
Docker 通過隔離機制,可以將服務器運行到極致
2. Docker歷史
參考:Docker的前生今世
2010 年,幾個搞 IT 的年輕人,在美國舊金山成立了一家名叫 dotCloud 的公司。dotCloud 的平臺即服務(Platform-as-a-Service, PaaS)提供商。底層技術上,dotCloud 平臺利用了 Linux 的 LXC 容器技術。
為了方便創建和管理這些容器,dotCloud 基于 Google 公司推出的 Go 語言開發了一套內部工具,之后被命名為 Docker。Docker 就是這樣誕生的。
如同 Docker 的 Logo 一樣,Docker 的思想來源于集裝箱。集裝箱解決了什么問題?在一艘大船上,可以把貨物規整的擺放起來,并且各種各樣的貨物被集裝箱標準化,集裝箱與集裝箱之間互不影響。那么就不需要專門運送水果的船和專門運送化學用品的船了。只要這些貨物封裝在不同的集裝箱里,就可以用一艘大船把它們都運走。
Docker 技術誕生之后,并沒有引起行業的關注。而 dotCloud 公司,作為一家小型創業企業,在激烈的競爭之下,也步履維艱。
正當他們快要堅持不下去的時候,腦子里蹦出了“開源”的想法。什么是“開源”?開源,就是開放源代碼。也就是將原來內部保密的程序源代碼開放給所有人,然后讓大家一起參與進來,貢獻代碼和意見。
有的軟件一開始就是開源的。也有的軟件,是混不下去,創造者又不想放棄,所以選擇開源。自己養不活,就吃“百家飯”嘛。2013 年 3 月,dotCloud 公司的創始人之一,Docker 之父,28 歲的 「Solomon?Hykes」 正式決定,將 Docker 項目開源。
不開則已,一開驚人。越來越多的 IT 工程師發現了 Docker 的優點,然后蜂擁而至,加入 Docker 開源社區。Docker 的人氣迅速攀升,速度之快,令人瞠目結舌。
開源當月, Docker 0.1 版本發布。此后的每一個月, Docker 都會發布一個版本。到 2014 年 6 月 9 日, Docker 1.0 版本正式發布。
此時的 Docker,已經成為行業里人氣最火爆的開源技術,沒有之一。甚至像 Google、微軟、Amazon、 VMware 這樣的巨頭們都對它青睞有加,表示將全力支持。
Docker 火了之后, dotCloud 公司干脆把公司名字也改成了 Docker Inc.
3. 對比虛擬化技術
虛擬機技術
缺點:
- 資源占用十分大
- 冗余步驟多
- 啟動慢
容器化技術:不是模擬的一個完整的操作系統
Docker 和 虛擬機技術 的不同:
- 傳統虛擬機技術,虛擬出一套硬件,運行一個完整的操作系統,在這個系統上安裝和運行軟件
- 容器內的應用直接運行在宿主機的內核上,容器沒有自己的內核,也沒有虛擬硬件,輕便快速,
- 每個容器互相隔離,每個容器都有一個自己的文件系統,互不影響
4. 為什么選擇Docker
更高效的利用系統資源
由于容器不需要進行硬件虛擬以及運行完整操作系統等額外開銷,Docker 對系統資源的利用率更高。無論是應用執行速度、內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。因此,相比虛擬機技術,一個相同配置的主機,往往可以運行更多數量的應用。
更快速的啟動時間
傳統的虛擬機技術啟動應用服務往往需要數分鐘,而 Docker 容器應用,由于直接運行于宿主內核,無需啟動完整的操作系統,因此可以做到秒級、甚至毫秒級的啟動時間。大大的節約了開發、測試、部署的時間。
一致的運行環境
開發過程中一個常見的問題是環境一致性問題。由于開發環境、測試環境、生產環境不一致,導致有些 bug 并未在開發過程中被發現。而 Docker 的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性,從而不會再出現「這段代碼在我機器上沒問題啊」 這類問題。
持續交付和部署
對開發和運維(DevOps)人員來說,最希望的就是一次創建或配置,可以在任意地方正常運行。
使用 Docker 可以通過定制應用鏡像來實現持續集成、持續交付、部署。開發人員可以通過 Dockerfile 來進行鏡像構建,并結合持續集成(Continuous Integration)系統進行集成測試,而運維人員則可以直接在生產環境中快速部署該鏡像,甚至結合持續部署(Continuous Delivery/Deployment)系統進行自動部署。
而且使用 Dockerfile 使鏡像構建透明化,不僅僅開發團隊可以理解應用運行環境,也方便運維團隊理解應用運行所需條件,幫助更好的在生產環境中部署該鏡像。
更輕松的遷移
由于 Docker 確保了執行環境的一致性,使得應用的遷移更加容易。Docker 可以在很多平臺上運行,無論是物理機、虛擬機、公有云、私有云,甚至是筆記本,其運行結果是一致的。因此用戶可以很輕易的將在一個平臺上運行的應用,遷移到另一個平臺上,而不用擔心運行環境的變化導致應用無法正常運行的情況。
更輕松的維護和擴展
Docker 使用的分層存儲以及鏡像的技術,使得應用重復部分的復用更為容易,也使得應用的維護更新更加簡單,基于基礎鏡像進一步擴展鏡像也變得非常簡單。此外,Docker 團隊同各個開源項目團隊一起維護了一大批高質量的 官方鏡像,既可以直接在生產環境使用,又可以作為基礎進一步定制,大大的降低了應用服務的鏡像制作成本。
引入Docker后:DevOps(開發、運維)
Docker技術的出現以后,DevOps的概念由然而生,即開發即運維
應用更快速的交付和部署
-
傳統:一堆幫助文檔,安裝程序
-
Docker:打包鏡像發布測試,一鍵運行
更便捷的升級和擴縮容
- 使用Docker之后,部署應用就和搭積木一樣
- 項目打包成一個鏡像,比如服務器A出現性能瓶頸,水平拓展,在服務器B上一鍵運行鏡像
更簡單的系統運維
- 容器化之后,開發、測試環境高度一致
更高效的計算資源利用
- Docker是內核級別的虛擬化,可以在一個物理機上運行很多容器實例,服務器性能可以被壓榨到極致
二、Docker安裝配置
1. Docker的基本組成
鏡像(image)
鏡像就是一個只讀的模板,可以通過這個模板創建容器服務,一個鏡像可以創建多個容器(最終服務運行或者項目運行就是在容器中)
容器(container)
- Docker利用容器技術,獨立運行的一個或一組應用。容器是用鏡像創建的運行實例。
- 它可以被啟用,開始,停止,刪除。每個容器都是相互隔離的,保證安全的平臺。
- 可以把容器看作是一個簡易版的Linux系統(包括root用戶權限,進程空間,用戶空間和網絡空間等)和運行在其中的應用程序。
- 容器的定義和鏡像幾乎一摸一樣,也是一堆層的統一視角,唯一區別在于容器的最上面那一層是可讀可寫的
倉庫(repository)
-
倉庫是集中存放鏡像文件的場所。
-
倉庫和倉庫注冊服務器(Registry)是有區別的,倉庫注冊服務器上往往存放著多個倉庫,每個倉庫中又包含了多個鏡像,每個鏡像有不同的標簽
-
倉庫分為公開倉庫(public)和私有倉庫(private)兩種形式
-
最大的開放倉庫是國外的 Docker Hub,存放了數量龐大的鏡像供用戶下載。
-
國內的公開倉庫包括阿里云,網易云都有容器服務器(需要配置鏡像加速)等
2. 環境準備
要安裝Docker Engine,您需要CentOS 7或8的維護版本。不支持或未測試存檔版本。
這里為阿里云 CentOS7 服務器,用 XShell 連接遠程服務器工具
# 系統內核 [root@iZ2ze3zdx4jq8v6hetjjuxZ /]# uname -r 3.10.0-1127.13.1.el7.x86_64# 系統版本 [root@iZ2ze3zdx4jq8v6hetjjuxZ /]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/"CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"3. 安裝
官網安裝教程十分詳細,可參照此教程:https://docs.docker.com/engine/install/centos/
1. 卸載舊版本
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
yum報告沒有安裝這些軟件包,即可
2. 安裝Docker軟件包
sudo yum install -y yum-utils3. 設置鏡像倉庫地址
# 默認是國外的 sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo# 換成阿里云鏡像地址 sudo yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo4. 安裝最新版Docker Engine和容器
安裝前建議先將將服務器上的軟件包信息現在本地緩存,以提高安裝軟件的速度
sudo yum makecache fast # docker-ce社區版(docker-ee企業版) sudo yum install docker-ce docker-ce-cli containerd.io
安裝完成后,Docker只安裝但并未啟動
5. 啟動Docker
sudo systemctl start docker然后可用docker version命令測試Docker是否安裝成功,并查看Docker的版本信息
6. 運行Hello World映像測試
sudo docker run hello-world
我們可用docker images查看Docker所有的鏡像信息
4. 卸載Docker方法
1. 卸載Docker依賴
# 1、卸載Docker依賴: Docker Engine,CLI和Containerd軟件包 sudo yum remove docker-ce docker-ce-cli containerd.io2. 刪除Docker資源
# 2、刪除Docker資源: 所有鏡像,容器和卷(主機上的鏡像,容器,卷或自定義配置文件不會自動刪除) sudo rm -rf /var/lib/docker/var/lib/docker為Docker的默認工作路徑
5. 阿里云鏡像加速
登錄阿里云賬號,找到產品與服務下的彈性計算中的容器鏡像服務
點擊進入,找到左側欄 鏡像加速器,選擇對應的系統,便可看到對用的命令
然后就可配置使用,逐條執行以下命令
到此則配置完畢
三、Docker run的流程和底層原理
1. 流程圖
2. 底層原理
Docker是怎么工作的?
- Docker 是一個 Client-Server 結構的系統,Docket 的守護進程運行在主機上,通過Socket從客戶端訪問
- DockerServer 接收到 DockerClient 的指令,就會執行這個命令
Docker為什么比VM快?
Docker有著比虛擬機更少的抽象層,由于Docker不需要Hypervisor實現硬件資源虛擬化,運行在Docker容器上的程序直接使用的都是實際物理機的硬件資源,因此在Cpu、內存利用率上Docker將會在效率上有明顯優勢。
Docker利用的是宿主機的內核,而不需要Guest OS,因此,當新建一個容器時,Docker不需要和虛擬機一樣重新加載一個操作系統,避免了引導、加載操作系統內核這個比較費時費資源的過程,當新建一個虛擬機時,虛擬機軟件需要加載Guest OS,這個新建過程是分鐘級別的,而Docker由于直接利用宿主機的操作系統則省略了這個過程,因此新建一個Docker容器只需要幾秒鐘。
| 操作系統 | 與宿主機共享OS | 宿主機OS上運行宿主機OS |
| 存儲大小 | 鏡像小,便于存儲與傳輸 | 鏡像龐大(vmdk等) |
| 運行性能 | 幾乎無額外性能損失 | 操作系統額外的cpu、內存消耗 |
| 移植性 | 輕便、靈活、適用于Linux | 笨重、與虛擬化技術耦合度高 |
| 硬件親和性 | 面向軟件開發者 | 面向硬件運維者 |
四、Docker常用命令
幫助文檔地址:https://docs.docker.com/reference/
1. 幫助命令
# 顯示docker的版本信息 docker version# 顯示docker的系統信息(包括鏡像和容器數量) docker info# 幫助命令 docker 命令 --help2. 鏡像命令
查看所有鏡像
# 查看本地主機所有的鏡像 docker images測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 12 months ago 13.3kB# 解釋 REPOSITORY 鏡像倉庫源 TAG 鏡像的標簽 IMAGE ID 鏡像的ID CREATED 鏡像的創建時間 SIZE 鏡像大小#可選項 --all , -a 列出所有鏡像 --quiet , -q 只顯示鏡像ID搜索鏡像
# 搜索鏡像 docker search 鏡像名測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 10414 [OK] mariadb MariaDB is a community-developed fork of MyS… 3865 [OK] mysql/mysql-server Optimized MySQL Server Docker images. Create… 762 [OK] percona Percona Server is a fork of the MySQL relati… 524 [OK] centos/mysql-57-centos7 MySQL 5.7 SQL database server 87 mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 79 centurylink/mysql Image containing mysql. Optimized to be link… 59 [OK] bitnami/mysql Bitnami MySQL Docker Image 47 [OK] deitch/mysql-backup REPLACED! Please use http://hub.docker.com/r… 41 [OK] databack/mysql-backup Back up mysql databases to... anywhere! 37 prom/mysqld-exporter 37 [OK] tutum/mysql Base docker image to run a MySQL database se… 35 schickling/mysql-backup-s3 Backup MySQL to S3 (supports periodic backup… 29 [OK] linuxserver/mysql A Mysql container, brought to you by LinuxSe… 27 circleci/mysql MySQL is a widely used, open-source relation… 20 centos/mysql-56-centos7 MySQL 5.6 SQL database server 20 arey/mysql-client Run a MySQL client from a docker container 17 [OK] mysql/mysql-router MySQL Router provides transparent routing be… 17 fradelg/mysql-cron-backup MySQL/MariaDB database backup using cron tas… 10 [OK] yloeffler/mysql-backup This image runs mysqldump to backup data usi… 7 [OK] openshift/mysql-55-centos7 DEPRECATED: A Centos7 based MySQL v5.5 image… 6 devilbox/mysql Retagged MySQL, MariaDB and PerconaDB offici… 3 ansibleplaybookbundle/mysql-apb An APB which deploys RHSCL MySQL 2 [OK] jelastic/mysql An image of the MySQL database server mainta… 1 widdpim/mysql-client Dockerized MySQL Client (5.7) including Curl… 1 [OK]# 可選項 -f, --filter filter 根據提供的條件過濾輸出 # 例如搜索STARS大于3000的 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker search mysql -f STARS=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 10414 [OK] mariadb MariaDB is a community-developed fork of MyS… 3865 [OK]下載鏡像
# 下載鏡像 docker pull 鏡像名[:tag]測試:
# 不指定版本號默認下載最新版latest [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker pull mysql Using default tag: latest latest: Pulling from library/mysql a076a628af6f: Pull complete #分層下載,docker image的核心:聯合文件系統 f6c208f3f991: Pull complete 88a9455a9165: Pull complete 406c9b8427c6: Pull complete 7c88599c0b25: Pull complete 25b5c6debdaf: Pull complete 43a5816f1617: Pull complete 1a8c919e89bf: Pull complete 9f3cf4bd1a07: Pull complete 80539cea118d: Pull complete 201b3cad54ce: Pull complete 944ba37e1c06: Pull complete Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest #真實地址# 指定版本號下載 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql a076a628af6f: Already exists f6c208f3f991: Already exists 88a9455a9165: Already exists 406c9b8427c6: Already exists 7c88599c0b25: Already exists 25b5c6debdaf: Already exists 43a5816f1617: Already exists 1831ac1245f4: Pull complete 37677b8c1f79: Pull complete 27e4ac3b0f6e: Pull complete 7227baa8c445: Pull complete Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7下載完再次查看所有鏡像,即可看到剛下載的鏡像
刪除鏡像
# 刪除鏡像 docker rmi`docker rmi -f 鏡像id`:刪除指定鏡像`docker rmi -f 鏡像id 鏡像id 鏡像id`:刪除指定多個鏡像`docker rmi -f $(docker images -aq)`:刪除全部鏡像測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 a70d36bc331a 5 days ago 449MB mysql latest c8562eaf9d81 5 days ago 546MB hello-world latest bf756fb1ae65 12 months ago 13.3kB #刪除指定鏡像 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker rmi -f a70d36bc331a Untagged: mysql:5.7 Untagged: mysql@sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df Deleted: sha256:a70d36bc331a13d297f882d3d63137d24b804f29fa67158c40ad91d5050c39c5 Deleted: sha256:50c77bf7bcddd1f1d97789d80ac2404eec22c860c104e858620d2a2e321f0ef7 Deleted: sha256:14244329b83dfc8982398ee4104a548385652d2bffb957798ff86a419013efd6 Deleted: sha256:6d990477f90af28473eb601a9bca22253f6381e053c5a8edda0a4f027e124a3c Deleted: sha256:ee0449796df204071589162fc16f8d65586312a40c68d1ba156c93c56f5e5ce8 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql latest c8562eaf9d81 5 days ago 546MB hello-world latest bf756fb1ae65 12 months ago 13.3kB #刪除所有鏡像 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker rmi -f $(docker images -aq) Untagged: mysql:latest Untagged: mysql@sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c Deleted: sha256:c8562eaf9d81c779cbfc318d6e01b8e6f86907f1d41233268a2ed83b2f34e748 Deleted: sha256:1b649b85960473808c6b812fc30c3f6a3ff1c0ffdcba5c9435daf01cf7d5373a Deleted: sha256:19cc889447050c16c797fd209fa114ee219de23facb37c00d4137a4ed4aad922 Deleted: sha256:3c793c06a026d276cf56a6a6a75527026ed9eafa7a7d21a438f7d5ed2314148e Deleted: sha256:1e1cd89a2bc183a7fea3dab0b543e9924278321ad0921c22cc088adbf3c2e77b Deleted: sha256:83b2015dfd000588c7c947b2d89b3be7a8e5a3abc6ab562668c358033aa779ec Deleted: sha256:d08533f1e2acc40ad561a46fc6a76b54c739e6b24f077c183c5709e0a6885312 Deleted: sha256:4f9d91a4728e833d1062fb65a792f06e22e425f63824f260c8b5a64b776ddc38 Deleted: sha256:20bf4c759d1b0d0e6286d2145453af4e0e1b7ba3d4efa3b8bce46817ad4109de Deleted: sha256:a9371bbdf16ac95cc72555c6ad42f79b9f03a82d964fe89d52bdc5f335a5f42a Deleted: sha256:5b02130e449d94f51e8ff6e5f7d24802246198749ed9eb064631e63833cd8f1d Deleted: sha256:ab74465b38bc1acb16c23091df32c5b7033ed55783386cb57acae8efff9f4b37 Deleted: sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864 Untagged: hello-world:latest Untagged: hello-world@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE3. 容器命令
有了鏡像才能夠創建容器,這里下載一個centos鏡像為以下測試做準備
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker pull centos Using default tag: latest latest: Pulling from library/centos 7a0437f04f83: Pull complete Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1 Status: Downloaded newer image for centos:latest docker.io/library/centos:latest新建容器并啟動
# 新建容器并啟動 docker run [可選參數] image# 參數說明 --name="Name" 容器名字,用于區分容器 -d 后臺方式運行 -it 使用交互方式運行,進入容器查看內容 -p 指定容器端口(小寫)-p ip:主機端口:容器端口-p 主機端口:容器端口(最常用)-P 容器端口容器端口 -P 隨機執行端口(大寫)測試:
#測試,啟動進入容器 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker run -it centos /bin/bash [root@22d0484830c9 /]# ls 查看容器內的centos,基礎版本,很多命令不完善 bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var#退出容器到主機 [root@22d0484830c9 /]# exit exit [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# ls 3000 cp cp.tar.gz f.sh hello.c install.sh login.sh read.sh time.sh列出所有運行的容器
# 列出所有運行的容器 docker ps [可選參數]# 參數說明 -a 列出當前正在運行以及歷史運行過的容器 -n=? 顯示最近創建的容器 -q 只顯示容器編號 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 22d0484830c9 centos "/bin/bash" About a minute ago Exited (0) About a minute ago condescending_mcnulty 3efe49d28bdd bf756fb1ae65 "/hello" 7 hours ago Exited (0) 7 hours ago confident_babbage 40fc94e7b0a4 bf756fb1ae65 "/hello" 7 months ago Exited (0) 7 months ago inspiring_lovelace [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -n=1 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 22d0484830c9 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago condescending_mcnulty [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -aq 22d0484830c9 3efe49d28bdd 40fc94e7b0a4退出容器
# 容器停止并退出 exit# 容器不停止退出 Ctrl+p+q刪除容器
# 刪除指定容器,不能刪除正在運行的容器,強制刪除用rm -f docker rm 容器id # 刪除所有容器 docker rm -f $(docker ps -aq) docker ps -a -q|xargs docker rm測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -aq 6518909c5fb2 3dfd73738e3b 22d0484830c9 3efe49d28bdd 40fc94e7b0a4 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker rm 6518909c5fb2 6518909c5fb2 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -aq 3dfd73738e3b 22d0484830c9 3efe49d28bdd 40fc94e7b0a4 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker rm -f $(docker ps -aq) 3dfd73738e3b 22d0484830c9 3efe49d28bdd 40fc94e7b0a4 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -aq啟動停止容器
docker start 容器id # 啟動容器 docker restart 容器id # 重啟容器 docker stop 容器id # 停止正在運行的容器 docker kill 容器id # 強制停止當前容器4. 常用其他命令
后臺啟動容器
# 后臺啟動容器 docker run -d 容器名測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker run -d centos 9606d8980f73ff313c64388f5f82e036072cc7191c3305ab80b371e37d8b1ad7 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9606d8980f73 centos "/bin/bash" 54 seconds ago Exited (0) 53 seconds ago youthful_dubinsky- 問題:后臺啟動容器,再用 docker ps 查看發現容器停止
- 原因:docker 容器使用后臺運行,就必須有一個前臺進程;如果僅僅后臺啟動,沒有應用來提供服務,就會自動停止
查看日志
docker logs [可選參數] 容器ID--details 顯示提供給日志的其他詳細信息-f, --follow 跟蹤日志輸出-n, --tail string 指定要顯示的日志條數 (默認為全部)-t, --timestamps 顯示時間戳測試:
# 后臺啟動容器,同時執行腳本不停打印zsr [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker run -d centos /bin/bash -c "while true;do echo zsr;sleep 1;done" 980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02 # 查看運行的容器,此時可以查看到 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 980daf06de58 centos "/bin/bash -c 'while…" 6 seconds ago Up 6 seconds distracted_germain # 查看日志信息,顯示時間戳,指定顯示10條日志 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker logs -t -n 10 980daf06de58 2021-01-25T04:53:47.619357189Z zsr 2021-01-25T04:53:48.621476433Z zsr 2021-01-25T04:53:49.623833490Z zsr 2021-01-25T04:53:50.626253957Z zsr 2021-01-25T04:53:51.628526460Z zsr 2021-01-25T04:53:52.630878536Z zsr 2021-01-25T04:53:53.633046201Z zsr 2021-01-25T04:53:54.635296632Z zsr 2021-01-25T04:53:55.637614256Z zsr 2021-01-25T04:53:56.640358130Z zsr查看容器中的進程
# 查看容器中的進程 docker top 容器ID測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker top 980daf06de58 UID PID PPID C STIME TTY TIME CMD root 28359 28339 0 12:52 ? 00:00:00 /bin/bash -c while true;do echo zsr;sleep 1;done root 29065 28359 0 12:58 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1查看鏡像元數據
# 查看鏡像元數據 docker inspect 容器ID測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker inspect 980daf06de58 [{"Id": "980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02","Created": "2021-01-25T04:52:46.079489883Z","Path": "/bin/bash","Args": ["-c","while true;do echo zsr;sleep 1;done"],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 28359,"ExitCode": 0,"Error": "","StartedAt": "2021-01-25T04:52:46.469990116Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55","ResolvConfPath": "/var/lib/docker/containers/980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02/resolv.conf","HostnamePath": "/var/lib/docker/containers/980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02/hostname","HostsPath": "/var/lib/docker/containers/980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02/hosts","LogPath": "/var/lib/docker/containers/980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02/980daf06de5878e2d3e5c048c7de92817e09e92f20d2d6242ecb15b9b7a5bd02-json.log","Name": "/distracted_germain","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"CgroupnsMode": "host","Dns": [],"DnsOptions": [],"DnsSearch": [],"ExtraHosts": null,"GroupAdd": null,"IpcMode": "private","Cgroup": "","Links": null,"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "","UsernsMode": "","ShmSize": 67108864,"Runtime": "runc","ConsoleSize": [0,0],"Isolation": "","CpuShares": 0,"Memory": 0,"NanoCpus": 0,"CgroupParent": "","BlkioWeight": 0,"BlkioWeightDevice": [],"BlkioDeviceReadBps": null,"BlkioDeviceWriteBps": null,"BlkioDeviceReadIOps": null,"BlkioDeviceWriteIOps": null,"CpuPeriod": 0,"CpuQuota": 0,"CpuRealtimePeriod": 0,"CpuRealtimeRuntime": 0,"CpusetCpus": "","CpusetMems": "","Devices": [],"DeviceCgroupRules": null,"DeviceRequests": null,"KernelMemory": 0,"KernelMemoryTCP": 0,"MemoryReservation": 0,"MemorySwap": 0,"MemorySwappiness": null,"OomKillDisable": false,"PidsLimit": null,"Ulimits": null,"CpuCount": 0,"CpuPercent": 0,"IOMaximumIOps": 0,"IOMaximumBandwidth": 0,"MaskedPaths": ["/proc/asound","/proc/acpi","/proc/kcore","/proc/keys","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/proc/scsi","/sys/firmware"],"ReadonlyPaths": ["/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]},"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/c836c661b72e93a97b704d62711facfd82b4f080359405a4382a8dca3f7ce2ed-init/diff:/var/lib/docker/overlay2/e7eaf7928b9265d758185f4ac2e84ab99cb6146cbf37d10a9d9b3ce1ad30ab3e/diff","MergedDir": "/var/lib/docker/overlay2/c836c661b72e93a97b704d62711facfd82b4f080359405a4382a8dca3f7ce2ed/merged","UpperDir": "/var/lib/docker/overlay2/c836c661b72e93a97b704d62711facfd82b4f080359405a4382a8dca3f7ce2ed/diff","WorkDir": "/var/lib/docker/overlay2/c836c661b72e93a97b704d62711facfd82b4f080359405a4382a8dca3f7ce2ed/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "980daf06de58","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/bash","-c","while true;do echo zsr;sleep 1;done"],"Image": "centos","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {"org.label-schema.build-date": "20201204","org.label-schema.license": "GPLv2","org.label-schema.name": "CentOS Base Image","org.label-schema.schema-version": "1.0","org.label-schema.vendor": "CentOS"}},"NetworkSettings": {"Bridge": "","SandboxID": "6a7fa868d1b07689ed1307cd6eaffa3d102c13440bddf41b7eedd526a328f03e","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/6a7fa868d1b0","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "ab462efd8637f15fd7aabe6250429571db2f4dc22e3248278dbe513af5e47e38","Gateway": "172.18.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.18.0.2","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:12:00:02","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "0524bfb4e90c798594ceca6e4099d5b1407f7dcef80435f023f4a1963a35fbb4","EndpointID": "ab462efd8637f15fd7aabe6250429571db2f4dc22e3248278dbe513af5e47e38","Gateway": "172.18.0.1","IPAddress": "172.18.0.2","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:12:00:02","DriverOpts": null}}}} ]進入當前正在運行的容器
容器通常都是使用后臺方式運行的,這時候可能需要進入容器,修改一些配置
# 方式一: 進入容器后開啟一個新的終端,可在里面進行操作(常用) docker exec -it 容器id /bin/bash# 方式二: 進入容器正在執行的終端,不會啟動新的進程 docker attach 容器ID測試:
# 測試方式一 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 980daf06de58 centos "/bin/bash -c 'while…" 2 hours ago Up 2 hours distracted_germain # 進入到容器 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker exec -it 980daf06de58 /bin/bash [root@980daf06de58 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var# 測試方式二 [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 980daf06de58 centos "/bin/bash -c 'while…" 2 hours ago Up 2 hours distracted_germain [root@iZ2ze3zdx4jq8v6hetjjuxZ ~]# docker attach 980daf06de58 zsr zsr zsr zsr zsr zsr zsr #進入死循環...從容器內拷貝文件到主機
# 從容器內拷貝文件到主機 docker cp 容器id:容器內路徑 目的主機路徑測試:
[root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker run -it centos /bin/bash [root@64b40f051756 /]# cd /home [root@64b40f051756 home]# ls # 在容器內部新建一個文件 [root@64b40f051756 home]# touch 1.txt [root@64b40f051756 home]# exit exit [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 64b40f051756 centos "/bin/bash" 4 minutes ago Exited (0) 59 seconds ago beautiful_ganguly c1b3f151ae12 centos "/bin/bash" 7 minutes ago Exited (127) 4 minutes ago nervous_lamarr 60b1f058de74 centos "/bin/bash" 14 minutes ago Exited (0) 12 minutes ago vibrant_jemison 980daf06de58 centos "/bin/bash -c 'while…" 2 hours ago Exited (137) 14 minutes ago distracted_germain d77c3cdfb7e2 centos "/bin/bash -c 'while…" 3 hours ago Exited (137) 2 hours ago relaxed_meninsky 7706ccced225 centos "/bin/bash -c 'whilr…" 3 hours ago Exited (1) 3 hours ago romantic_hopper 6eebf828ab4c centos "/bin/bash -c 'whilr…" 3 hours ago Exited (1) 3 hours ago brave_goldberg df422d73861f centos "/bin/bash" 3 hours ago Exited (0) 3 hours ago frosty_panini 744b9b044715 centos "/bin/bash" 3 hours ago Exited (127) 3 hours ago amazing_cori 9606d8980f73 centos "/bin/bash" 3 hours ago Exited (0) 3 hours ago youthful_dubinsky [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# cd /home [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# ls redis www zsr # 將容器內創建的1.txt拷貝到主機 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker cp 64b40f051756:/home/1.txt /home [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# ls 1.txt redis www zsr五、Docker命令實戰
1. 部署Nginx
# 1. 搜索鏡像 docker search nginx# 2. 下載鏡像 docker pull nginx# 3. 查看鏡像是否下載成功 docker images# 4. 啟動容器(-d:后臺運行 --name:容器名 -p:暴露端口 宿主機端口3344:容器端口80) docker run -d --name nginx01 -p 3344:80 nginx# 5. 查看容器是否啟動 docker ps# 6. 本機測試 curl localhost:3344完整代碼:
# 1. 搜索鏡像 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker search nginx -f STARS=6000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 14341 [OK] # 2. 下載鏡像 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx a076a628af6f: Pull complete 0732ab25fa22: Pull complete d7f36f6fe38f: Pull complete f72584a26f32: Pull complete 7125e4df9063: Pull complete Digest: sha256:10b8cc432d56da8b61b070f4c7d2543a9ed17c2b23010b43af434fd40e2ca4aa Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest# 3. 查看鏡像是否下載成功 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest f6d0b4767a6c 12 days ago 133MB centos latest 300e315adb2f 6 weeks ago 209MB# 4. 啟動容器(-d:后臺運行 --name:容器名 -p:暴露端口 宿主機端口3344:容器端口80) [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker run -d --name nginx01 -p 3344:80 nginx 1f9dbdf7f36d69731578314cd861eeed776174ea839100ae2f8987f1bd1b509a# 5. 查看容器是否啟動 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1f9dbdf7f36d nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:3344->80/tcp nginx01# 6. 本機測試 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# curl localhost:3344 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;} </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p><p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p> </body> </html># 進入容器 [root@iZ2ze3zdx4jq8v6hetjjuxZ home]# docker exec -it nginx01 /bin/bash root@1f9dbdf7f36d:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@1f9dbdf7f36d:/# cd /etc/nginx/ root@1f9dbdf7f36d:/etc/nginx# ls conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf2. 部署Tomcat
# 官方使用 # 之前我們都是后臺啟動,停止容器后,仍可以通過docker ps -a命令查到容器的使用記錄 # --rm表示用完就刪除容器及歷史記錄,通過命令查不到; docker run -it --rm tomcat:9.0 # tomcat啟動運行 [root@zsr home]# docker run -d -p 3355:8080 --name tomcat01 tomcat Unable to find image 'tomcat:latest' locally latest: Pulling from library/tomcat Digest: sha256:94cc18203335e400dbafcd0633f33c53663b1c1012a13bcad58cced9cd9d1305 Status: Downloaded newer image for tomcat:latest ffc2e1098b06fc0c0eb259fd93801e97087cbc33d0034a534208a44c491ab7a3 # 進入容器,發現webapps為空 [root@zsr home]# docker exec -it tomcat01 /bin/bash root@ffc2e1098b06:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@ffc2e1098b06:/usr/local/tomcat# cd webapps root@ffc2e1098b06:/usr/local/tomcat/webapps# ls3. 部署es+kibana
# es暴露的端口很多 # es十分耗內存 # es的數據一般需要放置在安全目錄!掛載# 啟動elasticsearch容器(啟動后會很卡頓,因為很占內存) docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2# 監控容器資源消耗(該命令也十分耗資源,服務器卡死) docker stats [容器ID]可以看到內存占用率很高;這時候趕緊關閉容器,增加內存的限制,再重新啟動一個容器
# 重新啟動elasticsearch容器,增加內存限制(-e ES_JAVA_OPTS="-Xms64m -Xmx512m" 最小64m 最大512m),防止服務器卡死 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2# 查看運行的容器 [root@zsr ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b6e7bc8063a5 elasticsearch:7.6.2 "/usr/local/bin/dock…" 39 seconds ago Up 37 seconds 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch01# 監控容器資源消耗 [root@zsr ~]# docker stats b6e7bc8063a5
可以看到內存占用被限制住,也不再卡了
六、Portainer可視化面板
1. 什么是 portainer ?
Docker 圖形化界面管理工具,提供一個后臺面板供我們操作
portainer(先用這個,不是最佳選項;學習CI/CD時再用 Rancher)
2. 下載
docker run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer3. 訪問測試
我們用docker ps命令查看一下正在運行的容器,可以看到 portainer 正在運行
[root@zsr ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b72d6033ae2e portainer/portainer "/portainer" 25 seconds ago Up 23 seconds 0.0.0.0:8088->9000/tcp vibrant_dhawan這時候我們訪問外網8088端口測試一下,這里訪問 阿里云服務器公網ip:8088 (注意安全組打開8088端口),就會出現如下界面
然后自己設置一個密碼創建用戶登錄
然后選擇 Local,再點擊 Connect
然后就進入了后臺管理界面
七、Docker鏡像講解
1. 鏡像是什么
鏡像 是一種輕量級,可執行的軟件包,用來打包軟件運行環境和基于運行軟件開發的軟件,它包含運行某個軟件所需的所有內容,包括代碼、運行時、庫、環境變量和配置文件。
所有的應用,直接打包成docker鏡像,就可以直接跑起來
如何獲取鏡像:
- 從遠程倉庫下載
- 自己制作一個 Dockerfile
2. Docker鏡像加載原理
UnionFS(聯合文件系統):一種分層、輕量級且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不通目錄掛載到同一個虛擬文件系統下(unite serveral directories into a single virtual filesystem)。Union 文件系統是 Docker 鏡像的基礎,鏡像可以通過分層來繼承,基于基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。
Docker 的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統就是 UnionFS 。
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引導加載kerel,Linux剛啟動時會加載 bootfs文件系統,在Docker鏡像的最底層時bootfs。這一層與我們典型的Linux/Unix內核是一樣的,包含boot加載器和內核。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs
rootfs(root file system)在bootfs之上,包含的就是典型的 Linux系統中的 /dev、/proc、/bin、/etc 等標準文件。rootfs 就是各種不同的操作系統發行版。
平時安裝的虛擬機的CentOS都是好幾個G,為什么Docker中才200MB?
對于一個精簡的 OS,rootfs 可以很小,只需要包含最基本的命令、工具和程序庫就可以了,因為底層使用的是主機的Kernel,自己只需要提供rootfs就可以了。由此可見,對于不同linux發行版,bootfs是基本一致的,rootfs會有差別,因此不同的發行版可以公用bootfs
3. 分層理解
下載示例
當我們下載一個鏡像的時候,可以看到,是一層一層的在下載!
為什么Docker鏡像要采取這種分層的結構呢?
資源共享:如果有多個鏡像從相同的Base鏡像構建而來,那么宿主機只需要在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像,這樣就可以為所有的容器服務,且每一層的鏡像都可以被共享。
-
查看鏡像分層方式可以通過docker image inspect命令
[root@zsr ~]# docker image inspect mysql:latest [{"Id": "sha256:c8562eaf9d81c779cbfc318d6e01b8e6f86907f1d41233268a2ed83b2f34e748","RepoTags": ["mysql:latest"],"RepoDigests": ["mysql@sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c"],"Parent": "","Comment": "","Created": "2021-01-18T23:25:55.311110441Z","Container": "1b772a9e2045f2e123c3ff1d11cc67c9a5fe78b33af9f6a9213aa8cf91f58a6b","ContainerConfig": {"Hostname": "1b772a9e2045","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"ExposedPorts": {"3306/tcp": {},"33060/tcp": {}},"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOSU_VERSION=1.12","MYSQL_MAJOR=8.0","MYSQL_VERSION=8.0.23-1debian10"],"Cmd": ["/bin/sh","-c","#(nop) ","CMD [\"mysqld\"]"],"Image": "sha256:ec58f145c941b51747ba729ab510ff01ca99fa797ec6f4bb8830f6e878e5c66e","Volumes": {"/var/lib/mysql": {}},"WorkingDir": "","Entrypoint": ["docker-entrypoint.sh"],"OnBuild": null,"Labels": {}},"DockerVersion": "19.03.12","Author": "","Config": {"Hostname": "","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"ExposedPorts": {"3306/tcp": {},"33060/tcp": {}},"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOSU_VERSION=1.12","MYSQL_MAJOR=8.0","MYSQL_VERSION=8.0.23-1debian10"],"Cmd": ["mysqld"],"Image": "sha256:ec58f145c941b51747ba729ab510ff01ca99fa797ec6f4bb8830f6e878e5c66e","Volumes": {"/var/lib/mysql": {}},"WorkingDir": "","Entrypoint": ["docker-entrypoint.sh"],"OnBuild": null,"Labels": null},"Architecture": "amd64","Os": "linux","Size": 546118644,"VirtualSize": 546118644,"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/468543c2b5fe15aad545f6f06c1a9447f7f12d9c4d846fd2a52cb7e777f95366/diff:/var/lib/docker/overlay2/b9d1aafa99f328fd606f9bc36617d8248d8b66abfe28b61ee29c7f3bb077992f/diff:/var/lib/docker/overlay2/63e10d9d7feec935439a9e001c681fdde27ce10a178b25c486acca518a4fbe4f/diff:/var/lib/docker/overlay2/f6e3f6c93b7d6e5470453603e17b3275677297d7c85edbe1a3ac742454d7a7ff/diff:/var/lib/docker/overlay2/59b36124a39b50c0f2b6c0543a0c4ee1ff6aeaa888f5debaf4ce22c38eaee34f/diff:/var/lib/docker/overlay2/ccff5c078d0a22a57e230f31c1794c6afa643697f9304ba588c301fdbe801ac0/diff:/var/lib/docker/overlay2/98dae5544da3f76f7754d291a7b5532955f06d0f70e7b18d8b962ad8f7800c9e/diff:/var/lib/docker/overlay2/4e76b3dfd15a940cc6c1cd1259f874286c3552eb3bcaa860ead70bbac102b999/diff:/var/lib/docker/overlay2/a95a0edca5d7b3a2b76349964602101194998b4d73b52da526a6067b49240ce3/diff:/var/lib/docker/overlay2/14ebff0838af4ff47eed6e8c712608b48ece23b8262043cd03391819bf2223ae/diff:/var/lib/docker/overlay2/9d91a52dd5189c9f9b4f731398fe1752b3a19155c569222c008dcb58ed214b43/diff","MergedDir": "/var/lib/docker/overlay2/dc057fc0332771f0a3b2e5f7a94c6bb3624e9a93cd350825c7816a378d312d77/merged","UpperDir": "/var/lib/docker/overlay2/dc057fc0332771f0a3b2e5f7a94c6bb3624e9a93cd350825c7816a378d312d77/diff","WorkDir": "/var/lib/docker/overlay2/dc057fc0332771f0a3b2e5f7a94c6bb3624e9a93cd350825c7816a378d312d77/work"},"Name": "overlay2"},"RootFS": {"Type": "layers","Layers": ["sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864","sha256:ef4a33cee7a02ffa3c1dd5d2618dcb95e37b899fb7e90d0bb2df32a37396e174","sha256:74c86dffd46f095d4961730b731a33b19c1abd19f0a7ec1b81ddf09e6d3dfe85","sha256:6d23902c2a54f36f80946d7225044b2681bac18570af3a58970e325b40ac0d60","sha256:c484a3b6d84133f3618780f11216facc49f743cefc86e04409f28784a3a0a733","sha256:0394a41efa739604258181808606eb47798a83383ff52241547583939ffb297c","sha256:98d98806c8acefda16226c37045e3733a751c3cb165fde1182cbc324cde06f78","sha256:d35a1217c926c4d5fc2e8a9f914e565d46a1da65f461e5cb9f09f7b34953bb97","sha256:9577a2d5d759695f1b0e92efd95e7e46b1ac4c4c75350bac0045c94bd308732a","sha256:d60ed0726e3751a08f8d1d1696f51bb3ac47276b2c4f271272f167f532b4285a","sha256:ab82e085fd825c64ed10839fcae191d2169657b9585438676d1f54fb626162be","sha256:c080af299e3f1cab9e0bbe183259aa64014e6c560fea1c0534ffe95b0180b2a3"]},"Metadata": {"LastTagTime": "0001-01-01T00:00:00Z"}} ]其中Layers就表示了每一層
理解
-
所有的 Docker鏡像都起始于一個基礎鏡像層,當進行修改或增加新的內容時,就會在當前鏡像層之上創建新的鏡像層
-
舉一個簡單的例子,假如基于 Ubuntu Linux 16.04 創建一個新的鏡像,這就是新鏡像的第一層;如果要在該鏡像中添加python包,就會在基礎鏡像層之上創建了新的一個鏡像層;如果繼續添加一個安全補丁,就會創建第三個鏡像層
在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合。下圖中舉了一個簡單的例子,每個鏡像層包含 3 個文件,而鏡像包含了來自兩個鏡像層的 6 個文件
上圖中的鏡像層跟之前圖中的略有區別,主要目的是便于展示文件。
下圖中展示了一個稍微復雜的三層鏡像,在外部看來整個鏡像只有 6 個文件,這是因為最上層中的文件7 是文件 5 的一個更新版本
這種情況下,上層鏡像層中的文件覆蓋了底層鏡像層中的文件。這樣就使得文件的更新版本作為一個新鏡像層添加到鏡像當中。
Docker 通過存儲引擎(新版本采用快照機制)的方式來實現鏡像層堆棧,并保證多鏡像層對外展示為統一的文件系統。
Linux 上可用的存儲引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顧名思義,每種存儲引擎都基于 Linux 中對應的文件系統或者塊設備技術,并且每種存儲引擎都有其獨有的性能特點。
Docker 在 Windows 上僅支持 windowsfilter 一種存儲引擎,該引擎基于 NTFS 文件系統之上實現了分層和 CoW[1]。
下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆疊并合并,對外提供統一的視圖。
特點
Docker鏡像都是只讀的,當容器啟動時,一個新的可寫層被加載到鏡像的頂部!
這一層就是我們通常說的容器層,容器之下的都叫鏡像層!
4. Commit鏡像
當我們通過鏡像啟動一個容器時,分為了兩層:容器層和鏡像層;鏡像層是可讀的,容器層可寫,我們的所有操作都是基于容器層,當我們對容器層修改完后,就可以再將修改后的容器層和不變的鏡像曾一起打包成一個新的鏡像,也就是本節要講的Commit鏡像
# 提交容器成為一個新的副本 docker commit docker commit -m="提交的描述信息" -a="作者" 容器id 目標鏡像名:[TAG]實戰測試:
# 啟動一個默認的Tomcat [root@zsr ~]# docker run -it -p 8088:8080 tomcat /bin/bash root@2594ca9eefcb:/usr/local/tomcat# cd webapps root@2594ca9eefcb:/usr/local/tomcat/webapps# ls root@2594ca9eefcb:/usr/local/tomcat/webapps# cd ..# 發現這個默認的Tomcat沒有webapps應用(官方鏡像默認沒有) root@2594ca9eefcb:/usr/local/tomcat# cd webapps root@2594ca9eefcb:/usr/local/tomcat/webapps# ls# 從webapps.dist拷貝到webapps中,使其有基本文件 root@2594ca9eefcb:/usr/local/tomcat/webapps# cd .. root@2594ca9eefcb:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@2594ca9eefcb:/usr/local/tomcat# cp -r webapps.dist/* webapps root@2594ca9eefcb:/usr/local/tomcat# cd webapps root@2594ca9eefcb:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager# 提交修改后的容器 [root@zsr ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7c548ecd440f tomcat "/bin/bash" 39 seconds ago Up 38 seconds 0.0.0.0:8088->8080/tcp brave_hertz [root@zsr ~]# docker commit -a "zsr" -m="copy files from webapps.dist to webapps" 7c548ecd440f tomcat_zsr:1.0 sha256:3be2283d4c0d49f733f33f849c5ae95415ba7dfb71672112c0f36391c694ef8b [root@zsr ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat_zsr 1.0 3be2283d4c0d 37 seconds ago 653MB mysql latest c8562eaf9d81 9 days ago 546MB tomcat 9.0 040bdb29ab37 2 weeks ago 649MB tomcat latest 040bdb29ab37 2 weeks ago 649MB nginx latest f6d0b4767a6c 2 weeks ago 133MB centos latest 300e315adb2f 7 weeks ago 209MB portainer/portainer latest 62771b0b9b09 6 months ago 79.1MB elasticsearch 7.6.2 f29a1ee41030 10 months ago 791MB八、容器數據卷
1. 什么是容器數據卷
docker的理念:將應用和環境打包成一個鏡像!通過鏡像啟動容器運行
- 問題:在容器中存儲的程序數據是需要持久化的,不能容器刪了數據也隨之刪除。比如,安裝一個MySQL容器,在其中存儲了大量數據,結果把容器刪了數據也沒了,就相當于刪庫跑路,這是不可能發生的
數據卷技術的引入:我們希望Docker容器產生的數據可以自動同步到本地,這樣容器刪了數據并不會丟失;同時數據也可在容器之間共享。這就是卷技術,也就是目錄的掛載,將容器內的目錄掛載到linux上
總結:容器的持久化和同步操作!容器間也可以實現數據共享!
2. 使用數據卷
docker run -it -v 主機目錄:容器內目錄測試:
[root@zsr ~]# docker run -it -v /home/test:/home centos /bin/bash啟動之后可以用docker inspect查看容器詳細信息,可以看到掛載的信息
我們開兩個窗口分別進入相對應掛載的目錄,在容器內/home目錄下新建一個文件,在主機/home/test目錄下同步出現該文件
同樣,如果我們關閉退出停止容器,在主機內的/home/test路徑下新建文件2.txt,在容器內/home下也會同步,我們再次打開容器可以看到2.txt
實戰:安裝MySQL
# 1. 下載mysql:5.7鏡像 [root@zsr test]# docker pull mysql:5.7 5.7: Pulling from library/mysql a076a628af6f: Already exists f6c208f3f991: Already exists 88a9455a9165: Already exists 406c9b8427c6: Already exists 7c88599c0b25: Already exists 25b5c6debdaf: Already exists 43a5816f1617: Already exists 1831ac1245f4: Pull complete 37677b8c1f79: Pull complete 27e4ac3b0f6e: Pull complete 7227baa8c445: Pull complete Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7# 2. 啟動mysql容器-d 后臺運行-p 端口映射-v 卷掛載-e 環境配置--name 容器名字 [root@zsr test]# docker run -d -p 3310: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 67271dad5e807c42dccfa4803c2743d59e7bf75937bb8adc0df504e151965385啟動之后,我們本機連接一下試試,記得打開阿里云服務器安全組設置的3310端口
點擊連接,連接成功,則說明docker部署成功
我們回到xshell,查看主機下的`/home/mysql`目錄,可以看到`conf`和`data`兩個目錄,我們進入`data`目錄,可以看到相關文件
如果我們在navicat中新建一個數據庫
再回到xhell,查看data目錄,可以看到新增了test,即進行了同步
如果我們刪除容器,數據仍在不會丟失,仍保留在本地
3. 具名和匿名掛載
匿名掛載
# 匿名掛載: -v:容器內路徑(沒有寫容器外路徑) docker run -d -P --name nginx01 -v /etc/nginx nginx# 查看所有volume的情況 docker volume ls具名掛載(常用)
# 具名掛載: -v 卷名:容器內路徑 docker run -d -P --name nginx02 -v specific-nginx:/etc/nginx nginx# 查看所有volume的情況 docker volume ls# 查specific-nginx卷的具體信息 docker volume inspect specific-nginx所有docker容器內的卷,沒有指定目錄情況下都是在/var/lib/docker/volumes/卷名/_data下
拓展
# 通過 容器內路徑:ro/rw 限制讀寫權限 ro:read only 只讀,該路徑文件只能通過宿主機來操作,容器內無法操作 rw:read write 可讀可寫docker run -d -P --name nginx02 -v specific-nginx:/etc/nginx:ro nginx docker run -d -P --name nginx02 -v specific-nginx:/etc/nginx:rw nginx4. 初識Dockerfile
Dockerfile就是用來構建 docker 鏡像的構建文件,就是一段命令腳本,通過這個腳本可以生成一個鏡像
通過這個腳本可以生成鏡像,鏡像是一層一層的,腳本中就是一個個命令,每個命令對應一層
# 創建一個dockerfile文件FROM centosVOLUME ["volume01","volume02"]CMD echo "----end----"CMD /bin/bash完整:
[root@zsr home]# ls 1.txt mysql redis test www zsr [root@zsr home]# mkdir docker-test-volume [root@zsr home]# ls 1.txt docker-test-volume mysql redis test www zsr [root@zsr home]# cd docker-test-volume/ [root@zsr docker-test-volume]# clear [root@zsr docker-test-volume]# pwd /home/docker-test-volume [root@zsr docker-test-volume]# vim dockerfile1 [root@zsr docker-test-volume]# cat dockerfile1 FROM centosVOLUME ["volume01","volume02"]CMD echo "----end----" CMD /bin/bash [root@zsr docker-test-volume]# docker build -f ./dockerfile1 -t zsr/centos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos---> 300e315adb2f Step 2/4 : VOLUME ["volume01","volume02"]---> Running in 50aca2e71aa4 Removing intermediate container 50aca2e71aa4---> fab18ace6a3a Step 3/4 : CMD echo "----end----"---> Running in 6de412d0d33e Removing intermediate container 6de412d0d33e---> dd29a1e732b7 Step 4/4 : CMD /bin/bash---> Running in bb9c9b146eea Removing intermediate container bb9c9b146eea---> 52d008bba0ac Successfully built 52d008bba0ac Successfully tagged zsr/centos:1.0然后就可以查到自己構建的鏡像
我們來通過自己創建的鏡像啟動容器,查看其中的內容,可以看到生成鏡像時自動掛載的數據卷目錄volume01和volume02
這兩個數據卷一定與外部有一個同步的目錄!且我們設置的是匿名掛載
通過以下命令查看具體的外部掛載路徑
docker inspect b7cf8107f9fb5. 數據卷容器
實現多個容器之間同步數據
啟動3個容器,通過我們自己創建的鏡像啟動
docker run -it --name docker01 zsr/centos:1.0 docker run -it --name docker02 --volumes-from docker01 zsr/centos:1.0 docker run -it --name docker03 --volumes-from docker01 zsr/centos:1.0
我們可以刪除docker01,但數據并不會丟失;只要有一個容器再用,就不會丟失,因為數據卷是采用雙向拷貝的技術,即使刪除了一個容器,但數據已經拷貝到了其他容器中
總結:
- 容器之間配置信息的傳遞,數據卷容器的聲明周期一直持續到沒有容器使用為止
- 如果數據同步到了本地,本地的數據是不會刪除的
九、DockerFile
1. DockerFile介紹
dockerfile是用來構建docker鏡像的文件
構建步驟:
dockerHub:https://hub.docker.com/
這里以搜索centos鏡像為例
我們點擊官方的鏡像源,會跳轉到一個github地址,里面就是dockerfile
可以看到功能很少,官方的鏡像都是基礎包,我們通常要搭建自己的鏡像
2. DockerFile的構建過程
基礎知識:
DockerFile是面向開發的,逐漸成為企業交付的標準,以后發布項目就是打包成一個鏡像,就需要編寫dockerfile文件,十分簡單!
3. DockerFile指令
常見指令
FROM # 基礎鏡像,從此開始構建 MAINTAINER # 鏡像作者,通常為姓名+郵箱 RUN # 鏡像構建時需要執行的命令 ADD # 在鏡像中需要添加的文件(比如基礎鏡像centos中要添加tomcat) WORKDIR # 鏡像的工作目錄 VOLUME # 容器數據卷,掛載主機的目錄 EXPOSE # 對外的暴露端口 CMD # 指定容器啟動時要運行的命令(只有最后一個生效,可被替代) ENTRYPOINT # 指定容器啟動時要運行的命令(可以追加命令) ONBUILD # 當構建一個被繼承DockerFile時就會運行ONBUILD指令 COPY # 類似ADD,將文件拷貝到鏡像中 ENV # 構建時的環境變量| MAINTAINER | 鏡像作者,通常為姓名+郵箱 |
| RUN | 鏡像構建時需要執行的命令 |
| ADD | 在鏡像中需要添加的文件(比如基礎鏡像centos中要添加tomcat) |
| WORKDIR | 鏡像的工作目錄 |
| VOLUME | 容器數據卷,掛載主機的目錄 |
| EXPOSE | 對外的暴露端口 |
| CMD | 指定容器啟動時要運行的命令(只有最后一個生效,可被替代) |
| ENTRYPOINT | 指定容器啟動時要運行的命令(可以追加命令) |
| ONBUILD | 當構建一個被繼承DockerFile時就會運行ONBUILD指令 |
| COPY | 類似ADD,將文件拷貝到鏡像中 |
| ENV | 構建時的環境變量 |
CMD和ENTRYPOINT的區別
測試CMD:
# 編寫的dockerfile文件 [root@zsr dockerfile]# cat test-CMD-dockerfile FROM centos CMD ["ls","-a"]# 構建鏡像 [root@zsr dockerfile]# docker build -f test-CMD-dockerfile -t cmdtest . Sending build context to Docker daemon 3.072kB Step 1/2 : FROM centos---> 300e315adb2f Step 2/2 : CMD ["ls","-a"]---> Running in 36cf3cc47759 Removing intermediate container 36cf3cc47759---> da35633333da Successfully built da35633333da Successfully tagged cmdtest:latest# 通過鏡像啟動容器,看到 ls -a 命令生效 [root@zsr dockerfile]# docker run da35633333da . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var# 啟動容器時追加 -l 命令,發現報錯,這是因為CMD會覆蓋以前的命令 [root@zsr dockerfile]# docker run da35633333da -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.# 啟動容器時追加 ls -al 命令,不報錯,這是因為CMD會覆蓋以前的命令 [root@zsr dockerfile]# docker run da35633333da ls -al total 56 drwxr-xr-x 1 root root 4096 Jan 30 10:58 . drwxr-xr-x 1 root root 4096 Jan 30 10:58 .. -rwxr-xr-x 1 root root 0 Jan 30 10:58 .dockerenv lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 340 Jan 30 10:58 dev drwxr-xr-x 1 root root 4096 Jan 30 10: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 119 root root 0 Jan 30 10: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 Jan 28 13:30 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測試ENTRYPOINT:
# 編寫的dockerfile文件 FROM centos ENTRYPOINT ["ls","-a"]# 構建鏡像 [root@zsr dockerfile]# docker build -f test-ENTRYPOINT-dockerfile -t entrypoint-test . Sending build context to Docker daemon 4.096kB Step 1/2 : FROM centos---> 300e315adb2f Step 2/2 : ENTRYPOINT ["ls","-a"]---> Running in 74c8223d1e35 Removing intermediate container 74c8223d1e35---> 27f4e359bf92 Successfully built 27f4e359bf92 Successfully tagged entrypoint-test:latest# 通過鏡像啟動容器,看到 ls -a 命令生效 [root@zsr dockerfile]# docker run 27f4e359bf92 . .. .dockerenv bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var# 啟動容器時追加 -l 命令,成功,這是因為ENTRYPOINT會追加到以前的命令 [root@zsr dockerfile]# docker run 27f4e359bf92 -l total 56 drwxr-xr-x 1 root root 4096 Jan 30 11:03 . drwxr-xr-x 1 root root 4096 Jan 30 11:03 .. -rwxr-xr-x 1 root root 0 Jan 30 11:03 .dockerenv lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin drwxr-xr-x 5 root root 340 Jan 30 11:03 dev drwxr-xr-x 1 root root 4096 Jan 30 11:03 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 119 root root 0 Jan 30 11:03 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 Jan 28 13:30 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 var4. 實戰:構建自己的CentOS
官網centosdockerfile:Docker Hub 大多數基礎鏡像都是scratch,然后添加所需的配置進行構建
FROM scratch ADD centos-8-x86_64.tar.xz / LABEL org.label-schema.schema-version="1.0" org.label-schema.name="CentOS Base Image" org.label-schema.vendor="CentOS" org.label-schema.license="GPLv2" org.label-schema.build-date="20201204" CMD ["/bin/bash"]1. 編寫dockerfile
基于官網的centos構建自己的centos,編寫一個centos-dockerfile
# 編寫自己的centos-dockerfile [root@zsr dockerfile]# vim centos-dockerfile [root@zsr dockerfile]# cat centos-dockerfile FROM centos MAINTAINER zsr<1412578784@qq.com>ENV MYPATH /usr/local WORKDIR $MYPATHRUN yum -y install vim RUN yum -y install net-toolsEXPOSE 8088CMD echo $MYPATH CMD echo "----end----" CMD /bin/bash2. 通過dockerfile構建鏡像
# 通過centos-dockerfile構建鏡像 # 命令: docker build -f dockerfile路徑 -t 鏡像名:[tag] . [root@zsr dockerfile]# docker build -f centos-dockerfile -t mycentos:0.1 . Sending build context to Docker daemon 2.048kB Step 1/10 : FROM centos---> 300e315adb2f Step 2/10 : MAINTAINER zsr<1412578784@qq.com>---> Running in 07cb579c0233 Removing intermediate container 07cb579c0233---> 47a448db7079 Step 3/10 : ENV MYPATH /usr/local---> Running in fb3d1ac73261 Removing intermediate container fb3d1ac73261---> 74e47975e555 Step 4/10 : WORKDIR $MYPATH---> Running in c596e71a7e68 Removing intermediate container c596e71a7e68---> 9588d6a7b4b9 Step 5/10 : RUN yum -y install vim---> Running in f005ef7c0b02 CentOS Linux 8 - AppStream 3.4 MB/s | 6.3 MB 00:01 CentOS Linux 8 - BaseOS 1.4 MB/s | 2.3 MB 00:01 CentOS Linux 8 - Extras 15 kB/s | 8.6 kB 00:00 Dependencies resolved. ================================================================================Package Arch Version Repository Size ================================================================================ Installing:vim-enhanced x86_64 2:8.0.1763-15.el8 appstream 1.4 M Installing dependencies:gpm-libs x86_64 1.20.7-15.el8 appstream 39 kvim-common x86_64 2:8.0.1763-15.el8 appstream 6.3 Mvim-filesystem noarch 2:8.0.1763-15.el8 appstream 48 kwhich x86_64 2.21-12.el8 baseos 49 kTransaction Summary ================================================================================ Install 5 PackagesTotal download size: 7.8 M Installed size: 30 M Downloading Packages: (1/5): gpm-libs-1.20.7-15.el8.x86_64.rpm 316 kB/s | 39 kB 00:00 (2/5): vim-filesystem-8.0.1763-15.el8.noarch.rp 1.2 MB/s | 48 kB 00:00 (3/5): which-2.21-12.el8.x86_64.rpm 1.6 MB/s | 49 kB 00:00 (4/5): vim-enhanced-8.0.1763-15.el8.x86_64.rpm 4.8 MB/s | 1.4 MB 00:00 (5/5): vim-common-8.0.1763-15.el8.x86_64.rpm 20 MB/s | 6.3 MB 00:00 -------------------------------------------------------------------------------- Total 3.5 MB/s | 7.8 MB 00:02 warning: /var/cache/dnf/appstream-02e86d1c976ab532/packages/gpm-libs-1.20.7-15.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY CentOS Linux 8 - AppStream 983 kB/s | 1.6 kB 00:00 Importing GPG key 0x8483C65D:Userid : "CentOS (CentOS Official Signing Key) <security@centos.org>"Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65DFrom : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial Key imported successfully Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transactionPreparing : 1/1 Installing : which-2.21-12.el8.x86_64 1/5 Installing : vim-filesystem-2:8.0.1763-15.el8.noarch 2/5 Installing : vim-common-2:8.0.1763-15.el8.x86_64 3/5 Installing : gpm-libs-1.20.7-15.el8.x86_64 4/5 Running scriptlet: gpm-libs-1.20.7-15.el8.x86_64 4/5 Installing : vim-enhanced-2:8.0.1763-15.el8.x86_64 5/5 Running scriptlet: vim-enhanced-2:8.0.1763-15.el8.x86_64 5/5 Running scriptlet: vim-common-2:8.0.1763-15.el8.x86_64 5/5 Verifying : gpm-libs-1.20.7-15.el8.x86_64 1/5 Verifying : vim-common-2:8.0.1763-15.el8.x86_64 2/5 Verifying : vim-enhanced-2:8.0.1763-15.el8.x86_64 3/5 Verifying : vim-filesystem-2:8.0.1763-15.el8.noarch 4/5 Verifying : which-2.21-12.el8.x86_64 5/5 Installed:gpm-libs-1.20.7-15.el8.x86_64 vim-common-2:8.0.1763-15.el8.x86_64 vim-enhanced-2:8.0.1763-15.el8.x86_64 vim-filesystem-2:8.0.1763-15.el8.noarchwhich-2.21-12.el8.x86_64 Complete! Removing intermediate container f005ef7c0b02---> 0c3951bc6949 Step 6/10 : RUN yum -y install net-tools---> Running in 4646de41c5d7 Last metadata expiration check: 0:00:11 ago on Sat Jan 30 04:10:15 2021. Dependencies resolved. ================================================================================Package Architecture Version Repository Size ================================================================================ Installing:net-tools x86_64 2.0-0.52.20160912git.el8 baseos 322 kTransaction Summary ================================================================================ Install 1 PackageTotal download size: 322 k Installed size: 942 k Downloading Packages: net-tools-2.0-0.52.20160912git.el8.x86_64.rpm 4.4 MB/s | 322 kB 00:00 -------------------------------------------------------------------------------- Total 692 kB/s | 322 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transactionPreparing : 1/1 Installing : net-tools-2.0-0.52.20160912git.el8.x86_64 1/1 Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64 1/1 Verifying : net-tools-2.0-0.52.20160912git.el8.x86_64 1/1 Installed:net-tools-2.0-0.52.20160912git.el8.x86_64 Complete! Removing intermediate container 4646de41c5d7---> 72be4892b90e Step 7/10 : EXPOSE 8088---> Running in 57afa2232032 Removing intermediate container 57afa2232032---> afadc63b8b9b Step 8/10 : CMD echo $MYPATH---> Running in 29d0dd8ea502 Removing intermediate container 29d0dd8ea502---> 909e565c58a0 Step 9/10 : CMD echo "----end----"---> Running in 04c2f5807be3 Removing intermediate container 04c2f5807be3---> d4dcc5359a4d Step 10/10 : CMD /bin/bash---> Running in 10a0d1c49ad2 Removing intermediate container 10a0d1c49ad2---> 1c97191097fc Successfully built 1c97191097fc Successfully tagged mycentos:0.1然后用docker images命令就可以查看到構建的鏡像mycentos
同樣,我們可以用docker history命令查看鏡像的構建過程
3. 通過鏡像啟動容器
[root@zsr dockerfile]# docker run -it mycentos:0.1 [root@a5f99e5c1589 local]# pwd /usr/local [root@a5f99e5c1589 local]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.18.0.5 netmask 255.255.0.0 broadcast 172.18.255.255ether 02:42:ac:12:00:05 txqueuelen 0 (Ethernet)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0loop txqueuelen 1000 (Local Loopback)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0[root@a5f99e5c1589 local]# vim 1.txt對比之前官方的centos,新增了ifconfig、vim等命令
5. 實戰:構建自己的Tomcat
1. 準備鏡像文件
準備Tomcat壓縮包,而Tomcat運行需要依賴于jdk,所以還需要jdk的壓縮包
tomcat下載地址:https://tomcat.apache.org/download-90.cgi
jdk下載地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
然后將兩個壓縮包通過xftp拷貝到服務器的/home/tomcat目錄下
可在服務器中查看
2. 編寫dockerfile文件
編寫dockerfile文件,官方命名為Dockerfile,這樣就不需要通過-f指定,build時會自動尋找這個文件
FROM centos MAINTAINER zsr<1412578784@qq.com>COPY readme.txt /usr/local/readme.txtADD jdk-8u281-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.41.tar.gz /usr/local/RUN yum -y install vimENV MYPATH /usr/local WORKDIR $MYPATHENV JAVA_HOME /usr/local/jdk ENV CALSSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.41 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.41 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/binEXPOSE 8080CMD /usr/local/apache-tomcat-9.0.41/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.41/bin/logs/catalina.out3. 構建鏡像
[root@zsr tomcat]# docker build -t mytomcat . Sending build context to Docker daemon 155.2MB Step 1/15 : FROM centos---> 300e315adb2f Step 2/15 : MAINTAINER zsr<1412578784@qq.com>---> Using cache---> 47a448db7079 Step 3/15 : COPY readme.txt /usr/local/readme.txt---> 8dd0d2ce8867 Step 4/15 : ADD jdk-8u281-linux-x64.tar.gz /usr/local/---> 7c5ab3a8ed6e Step 5/15 : ADD apache-tomcat-9.0.41.tar.gz /usr/local/---> e2f1d80dde55 Step 6/15 : RUN yum -y install vim---> Running in 75ad35b83d68 CentOS Linux 8 - AppStream 4.2 MB/s | 6.3 MB 00:01 CentOS Linux 8 - BaseOS 633 kB/s | 2.3 MB 00:03 CentOS Linux 8 - Extras 14 kB/s | 8.6 kB 00:00 Dependencies resolved. ================================================================================Package Arch Version Repository Size ================================================================================ Installing:vim-enhanced x86_64 2:8.0.1763-15.el8 appstream 1.4 M Installing dependencies:gpm-libs x86_64 1.20.7-15.el8 appstream 39 kvim-common x86_64 2:8.0.1763-15.el8 appstream 6.3 Mvim-filesystem noarch 2:8.0.1763-15.el8 appstream 48 kwhich x86_64 2.21-12.el8 baseos 49 kTransaction Summary ================================================================================ Install 5 PackagesTotal download size: 7.8 M Installed size: 30 M Downloading Packages: (1/5): gpm-libs-1.20.7-15.el8.x86_64.rpm 495 kB/s | 39 kB 00:00 (2/5): vim-filesystem-8.0.1763-15.el8.noarch.rp 1.5 MB/s | 48 kB 00:00 (3/5): which-2.21-12.el8.x86_64.rpm 201 kB/s | 49 kB 00:00 (4/5): vim-enhanced-8.0.1763-15.el8.x86_64.rpm 2.3 MB/s | 1.4 MB 00:00 (5/5): vim-common-8.0.1763-15.el8.x86_64.rpm 2.9 MB/s | 6.3 MB 00:02 -------------------------------------------------------------------------------- Total 792 kB/s | 7.8 MB 00:10 warning: /var/cache/dnf/appstream-02e86d1c976ab532/packages/gpm-libs-1.20.7-15.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY CentOS Linux 8 - AppStream 1.0 MB/s | 1.6 kB 00:00 Importing GPG key 0x8483C65D:Userid : "CentOS (CentOS Official Signing Key) <security@centos.org>"Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65DFrom : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial Key imported successfully Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transactionPreparing : 1/1 Installing : which-2.21-12.el8.x86_64 1/5 Installing : vim-filesystem-2:8.0.1763-15.el8.noarch 2/5 Installing : vim-common-2:8.0.1763-15.el8.x86_64 3/5 Installing : gpm-libs-1.20.7-15.el8.x86_64 4/5 Running scriptlet: gpm-libs-1.20.7-15.el8.x86_64 4/5 Installing : vim-enhanced-2:8.0.1763-15.el8.x86_64 5/5 Running scriptlet: vim-enhanced-2:8.0.1763-15.el8.x86_64 5/5 Running scriptlet: vim-common-2:8.0.1763-15.el8.x86_64 5/5 Verifying : gpm-libs-1.20.7-15.el8.x86_64 1/5 Verifying : vim-common-2:8.0.1763-15.el8.x86_64 2/5 Verifying : vim-enhanced-2:8.0.1763-15.el8.x86_64 3/5 Verifying : vim-filesystem-2:8.0.1763-15.el8.noarch 4/5 Verifying : which-2.21-12.el8.x86_64 5/5 Installed:gpm-libs-1.20.7-15.el8.x86_64 vim-common-2:8.0.1763-15.el8.x86_64 vim-enhanced-2:8.0.1763-15.el8.x86_64 vim-filesystem-2:8.0.1763-15.el8.noarchwhich-2.21-12.el8.x86_64 Complete! Removing intermediate container 75ad35b83d68---> 223e446850cd Step 7/15 : ENV MYPATH /usr/local---> Running in 75bb312ba150 Removing intermediate container 75bb312ba150---> 0365605d3b03 Step 8/15 : WORKDIR $MYPATH---> Running in 3a21e6991d81 Removing intermediate container 3a21e6991d81---> 29130451ac38 Step 9/15 : ENV JAVA_HOME /usr/local/jdk---> Running in 1ecd36c1d9f7 Removing intermediate container 1ecd36c1d9f7---> fe6bf481c29a Step 10/15 : ENV CALSSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar---> Running in 02236cc9eea3 Removing intermediate container 02236cc9eea3---> c30c9a3c9b7a Step 11/15 : ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.41---> Running in b6e97820a257 Removing intermediate container b6e97820a257---> adc11a0fcc4b Step 12/15 : ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.41---> Running in b92bfa0ad8ab Removing intermediate container b92bfa0ad8ab---> 9604504f196d Step 13/15 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin---> Running in 025388f720e6 Removing intermediate container 025388f720e6---> 486df4c3100f Step 14/15 : EXPOSE 8080---> Running in 46a3f73f7a63 Removing intermediate container 46a3f73f7a63---> 3decd97962e6 Step 15/15 : CMD /usr/local/apache-tomcat-9.0.41/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.41/bin/logs/catalina.out---> Running in b0c9afffc1f1 Removing intermediate container b0c9afffc1f1---> 42338715d10f Successfully built 42338715d10f Successfully tagged mytomcat:latest4. 啟動容器
[root@zsr tomcat]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat latest 42338715d10f About a minute ago 640MB entrypoint-test latest 27f4e359bf92 4 hours ago 209MB cmdtest latest da35633333da 4 hours ago 209MB mycentos 0.1 1c97191097fc 11 hours ago 291MB zsr/centos 1.0 52d008bba0ac 2 days ago 209MB tomcat_zsr 1.0 3be2283d4c0d 2 days ago 653MB mysql 5.7 a70d36bc331a 11 days ago 449MB mysql latest c8562eaf9d81 11 days ago 546MB tomcat 9.0 040bdb29ab37 2 weeks ago 649MB tomcat latest 040bdb29ab37 2 weeks ago 649MB nginx latest f6d0b4767a6c 2 weeks ago 133MB centos latest 300e315adb2f 7 weeks ago 209MB portainer/portainer latest 62771b0b9b09 6 months ago 79.1MB elasticsearch 7.6.2 f29a1ee41030 10 months ago 791MB [root@zsr tomcat]# docker run -d -P 47.95.238.165:8088:8080 --name zsrtomcat -v /home/tomcat/test:/usr/local/apache-tomcat-9.0.41/webapps/test -v /home/tomcat/logs:/usr/local/apache-tomcat-9.0.41/logs mytomcat 04d4ec8d3986250927c3d2174ac11130e3b29b943b18fd908e434cf7545d4aab [root@zsr tomcat]# ls apache-tomcat-9.0.41.tar.gz Dockerfile jdk-8u281-linux-x64.tar.gz logs readme.txt test5. 進入容器
[root@zsr tomcat]# docker exec -it 04d4ec8d3986 /bin/bash [root@04d4ec8d3986 local]# pwd /usr/local [root@04d4ec8d3986 local]# ls -l total 52 drwxr-xr-x 1 root root 4096 Jan 30 14:58 apache-tomcat-9.0.41 drwxr-xr-x 2 root root 4096 Nov 3 15:22 bin drwxr-xr-x 2 root root 4096 Nov 3 15:22 etc drwxr-xr-x 2 root root 4096 Nov 3 15:22 games drwxr-xr-x 2 root root 4096 Nov 3 15:22 include drwxr-xr-x 8 10143 10143 4096 Dec 9 12:50 jdk1.8.0_281 drwxr-xr-x 2 root root 4096 Nov 3 15:22 lib drwxr-xr-x 3 root root 4096 Dec 4 17:37 lib64 drwxr-xr-x 2 root root 4096 Nov 3 15:22 libexec -rw-r--r-- 1 root root 0 Jan 30 12:18 readme.txt drwxr-xr-x 2 root root 4096 Nov 3 15:22 sbin drwxr-xr-x 5 root root 4096 Dec 4 17:37 share drwxr-xr-x 2 root root 4096 Nov 3 15:22 src [root@04d4ec8d3986 local]# cd apache-tomcat-9.0.41/ [root@04d4ec8d3986 apache-tomcat-9.0.41]# ls -l total 148 -rw-r----- 1 root root 18982 Dec 3 11:48 BUILDING.txt -rw-r----- 1 root root 5409 Dec 3 11:48 CONTRIBUTING.md -rw-r----- 1 root root 57092 Dec 3 11:48 LICENSE -rw-r----- 1 root root 2333 Dec 3 11:48 NOTICE -rw-r----- 1 root root 3257 Dec 3 11:48 README.md -rw-r----- 1 root root 6898 Dec 3 11:48 RELEASE-NOTES -rw-r----- 1 root root 16507 Dec 3 11:48 RUNNING.txt drwxr-x--- 2 root root 4096 Dec 3 11:48 bin drwx------ 2 root root 4096 Dec 3 11:48 conf drwxr-x--- 2 root root 4096 Dec 3 11:45 lib drwxr-xr-x 2 root root 4096 Jan 30 15:06 logs drwxr-x--- 2 root root 4096 Dec 3 11:45 temp drwxr-x--- 1 root root 4096 Jan 30 15:06 webapps drwxr-x--- 2 root root 4096 Dec 3 11:43 work6. 訪問測試
同樣,用公網IP:8088可以訪問到
7. 發布項目
我們已經做了卷掛載,本機的/home/tomcat/test掛載到容器的/usr/local/apache-tomcat-9.0.41/webapps/test目錄,因此我們只需要在本機對應目錄項發布項目就會自動同步到容器中
我們在/home/tomcat/test目錄下新建WEB-INF目錄,在其中創建web.xml文件
然后在test目錄下創建一個index.jsp頁面
然后瀏覽器輸入localhost:8088/test即可看到頁面
6. 發布鏡像到 Docker Hub
首先要有自己Docker Hub的賬號
1. 登錄 Docker Hub
docker login命令用于登錄
[root@zsr test]# docker login --helpUsage: 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 Username2. 提交到 Docker Hub
用docker tag命令重命名要發布到鏡像,名稱格式為:賬戶名/鏡像名:版本號
[root@zsr test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat latest 42338715d10f 6 days ago 640MB [root@zsr test]# docker tag 42338715d10f bareth/tomcat:1.0 [root@zsr test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE bareth/tomcat 1.0 42338715d10f 6 days ago 640MB mytomcat latest 42338715d10f 6 days ago 640MB然后push即可
[root@zsr ~]# docker push bareth/tomcat:1.0 The push refers to repository [docker.io/bareth/tomcat] 95a2375d854b: Pushing 15.68MB/58.05MB 028764aa589d: Pushing 5.345MB/15.83MB aea92a4c5330: Pushing 4.422MB/356.6MB ea60ecf88e36: Pushed 2653d992f4ef: Pushing 10.95MB/209.3MB7. 發布鏡像到阿里云鏡像
1. 創建阿里云鏡像倉庫
首先登錄阿里云,找到 容器鏡像服務
點擊進入,然后 創建一個鏡像倉庫
倉庫類型選擇 本地倉庫
便成功創建了倉庫
我們點擊進入剛創建的倉庫可以查看相關信息
2. 提交到阿里云鏡像倉庫
1、登錄阿里云Docker Registry
- 登錄的用戶名為阿里云賬號全名,密碼為開通服務時設置的密碼
2、使用docker tag命令重命名要發布的鏡像
[root@zsr test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat latest 42338715d10f 6 days ago 640MB [root@zsr test]# docker tag 42338715d10f registry.cn-beijing.aliyuncs.com/bareth/docker-test:1.0 [root@zsr ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat latest 42338715d10f 2 weeks ago 640MB registry.cn-beijing.aliyuncs.com/bareth/docker-test 1.0 42338715d10f 2 weeks ago 640MB3、push到阿里云鏡像倉庫
[root@zsr ~]# docker push registry.cn-beijing.aliyuncs.com/bareth/docker-test:1.0 The push refers to repository [docker.io/bareth/tomcat]小結
十、Docker網絡
1. Docker網絡原理
當我們用ip addr命令查看服務器內部網絡地址時,可以發現三個地址:
- 127.0.0.1 本機回環地址
- 172.17.223.207 服務器內網IP地址
- 172.18.0.1 docker0地址
這里的docker0地址就是安裝docker時,采用 橋接模式 使用 evth-pair 技術分配的地址
==docker是如何處理容器網絡訪問的?==比如有一個tomcat容器,一個mysql容器;tomcat中運行著一個web項目,這個項目需要訪問mysql。這是如何實現的呢?
我們首先啟動一個tomcat容器
# 啟動一個容器 [root@zsr ~]# docker run -d -P --name tomcat01 tomcat Unable to find image 'tomcat:latest' locally latest: Pulling from library/tomcat b9a857cbf04d: Pull complete d557ee20540b: Pull complete 3b9ca4f00c2e: Pull complete 667fd949ed93: Pull complete 661d3b55f657: Pull complete 511ef4338a0b: Pull complete a56db448fefe: Pull complete 00612a99c7dc: Pull complete 326f9601c512: Pull complete c547db74f1e1: Pull complete Digest: sha256:94cc18203335e400dbafcd0633f33c53663b1c1012a13bcad58cced9cd9d1305 Status: Downloaded newer image for tomcat:latest c3b8a6a222bfcd73d5cf350d330b3a1c536d0eb5a0676eb24e193664659f2fcd然后我們查看容器內部網絡地址,可以發現 eth0@if89 這個ip地址127.0.0.1,這是docker分配的
# 查看容器內部網絡地址,可以發現 eth0@if89 這個ip地址,這是docker分配的 [root@zsr ~]# docker exec -it tomcat01 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever 88: eth0@if89: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0valid_lft forever preferred_lft forever我們ping該容器內地址,發現可以ping通,因為127.0.0.2和docker0地址127.0.0.1網絡前綴相同,是處于統一網段的,所以可以ping通
# ping容器內地址,發現可以ping通docker容器內部 [root@zsr ~]# ping 172.18.0.2 PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data. 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.100 ms 64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.071 ms 64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.070 ms原理:
- 每啟動一個docker容器時,docker就會給該容器分配一個ip地址
我們再次在服務器上使用ip addr測試,可以發現多了一對網絡地址,這就是啟動tomcat容器docker為其分配的地址
如果我們再啟動一個tomcat容器,可以看到又多了一對網絡地址
我們發現每次新增的網絡地址都是一對一對的88/89 90/91,這就是evth-pair技術,就是一對虛擬設備接口,成對出現,一段連著協議,一段彼此相連;容器內的88連接了主機的89,容器內的90連接了主機的91;
evth-pair充當了一個橋梁,實現了主機可以ping通容器內部ip地址,用于連接各種虛擬網絡設備
那么 tomcar01和tomcat02 這兩個容器能否ping通呢?當然是可以的,因為兩個容器內的ip地址都橋接了主機相應的ip地址,都與docker0地址處于同一網段,因此可以ping通
# tomcat02 ping tomcat01可以ping通 [root@zsr ~]# docker exec -it tomcat02 ping 172.18.0.2 PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data. 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.127 ms 64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.109 ms 64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.100 ms可用docker netowork命令查看該網橋中的所有配置
[root@zsr ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 81fa37acd3b5 bridge bridge local d1c3276f2d1f host host local 40b12350fa4a none null local [root@zsr ~]# docker network inspect 81fa37acd3b5 [{"Name": "bridge","Id": "81fa37acd3b5fe63542a50cb6dda629a7434fa9fdebccedb7e8c24e859a31b76","Created": "2021-02-06T20:58:24.660018691+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.18.0.0/16","Gateway": "172.18.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"1cc06da893c10d4ef1bdf7e590860b44cf55a0c506b57b64dda44551ef06d816": {"Name": "tomcat03","EndpointID": "1c3a39f04598dc4b966f51b54e82c15a77c522e49fbfe618d70668332abc9ba3","MacAddress": "02:42:ac:12:00:04","IPv4Address": "172.18.0.4/16","IPv6Address": ""},"c3b8a6a222bfcd73d5cf350d330b3a1c536d0eb5a0676eb24e193664659f2fcd": {"Name": "tomcat01","EndpointID": "1b5015b0de628870b5498984aae24c0175dd8cb2663de9c9c6f6bce0694771e0","MacAddress": "02:42:ac:12:00:02","IPv4Address": "172.18.0.2/16","IPv6Address": ""},"ff19965390f0f4231130227b252290ea759d407ecbb2b0c0dcc11261d5687f26": {"Name": "tomcat02","EndpointID": "8ae0342e9e42fe3b9a19c70f1646500ae7dae519781719b7b8097eb9b43b5811","MacAddress": "02:42:ac:12:00:03","IPv4Address": "172.18.0.3/16","IPv6Address": ""}},"Options": {"com.docker.network.bridge.default_bridge": "true","com.docker.network.bridge.enable_icc": "true","com.docker.network.bridge.enable_ip_masquerade": "true","com.docker.network.bridge.host_binding_ipv4": "0.0.0.0","com.docker.network.bridge.name": "docker0","com.docker.network.driver.mtu": "1500"},"Labels": {}} ]結論:容器和容器之間是可以互相ping通的
所有的容器不指定網絡的情況下,都是通過 docker0路由的,docker會給容器分配一個默認的可用ip
- Docker 使用的是Linux的橋接,宿主機中是一個Docker容器的網橋docker0
- Docker 中所有的網絡接口都是虛擬的,轉發效率高,只要容器刪除,對應的網橋就刪除
2. 容器互聯–link
如果我們編寫了一個微服務,連接數據庫的ip地址變化了,此時數據連接就會斷開,服務不可用;如果此時能夠通過容器名字連接數據庫,就可以解決數據庫連接的問題;
如果tomcat01直接通過pingtomcat02的容器名,會報錯
[root@zsr ~]# docker exec -it tomcat01 ping tomcat02 ping: tomcat02: Name or service not known那么如何解決這個問題呢?可以在創建容器時用--link指定連接的容器,此時就可以通過容器名來ping通了
[root@zsr ~]# docker run -d -P --name tomcat03 --link tomcat01 tomcat 1cc06da893c10d4ef1bdf7e590860b44cf55a0c506b57b64dda44551ef06d816 [root@zsr ~]# docker exec -it tomcat03 ping tomcat01 PING tomcat01 (172.18.0.2) 56(84) bytes of data. 64 bytes from tomcat01 (172.18.0.2): icmp_seq=1 ttl=64 time=0.127 ms 64 bytes from tomcat01 (172.18.0.2): icmp_seq=2 ttl=64 time=0.103 ms 64 bytes from tomcat01 (172.18.0.2): icmp_seq=3 ttl=64 time=0.103 ms但是反過來ping則無法ping通
[root@zsr ~]# docker exec -it tomcat01 ping tomcat03 ping: tomcat03: Name or service not known原理:通過--link 使tomcat03 在本地hosts中配置了 tomcat02的ip與容器名的映射
3. 自定義網絡
# 查看所有的網絡 [root@zsr ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 81fa37acd3b5 bridge bridge local d1c3276f2d1f host host local 40b12350fa4a none null local網絡模式
- bridge:橋接(默認)
- none:不配置網絡
- host:主機模式,和宿主機共享網絡
- container:容器網絡聯通(使用少!)
測試:
當我們啟動一個容器時,其實有默認參數--net bridge,這也就是docker0,是默認的方式,上述提到可以用--link進行互聯實現通過容器名訪問,但是比較繁瑣,不建議使用;
# 啟動一個容器時帶默認參數 --net bridge docker run -d -P --name mytomcat tomcat docker run -d -P --name mytomcat --net bridge tomcat建議自定義一個網絡,所有的服務都在自定義的網絡中進行使用!
# 創建一個網絡mynet,采用默認的橋接模式,子網地址192.168.0.0,網關192.168.0.1 [root@zsr ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 2e6be259e1f43f884fbf9e24aa3cc1b238b91bd1e9be3ba0abcfbefd3e106450 [root@zsr ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 81fa37acd3b5 bridge bridge local d1c3276f2d1f host host local 2e6be259e1f4 mynet bridge local 40b12350fa4a none null local可查看自定義網絡的詳細信息
我們指定使用自定義網絡mynet來啟動兩個容器
然后再查看mynet的詳細信息,可以看到這兩個容器以及分配的IP地址
再次測試ping連接,發現自定義的網絡解決了docker0的缺點,可以直接通過容器名來訪問
應用場景:
不同的集群(redis,mysql)用不同的網絡,使用自己的子網,保證集群的安全及健康
4. 網絡聯通
上述我們啟動了四個容器,分別是默認docker0網絡下的tomcat01/tomcat02,自定義網絡mynet網絡下的mynet-tomcat01/mynet-tomcat02
我們畫個圖來理解一下
此時可以實現tomcat01到mynet-tomcat01的互聯嗎?答案當然是否定的,因為是處于不同的網段,我們可以進行測試
那么怎么實現tomcat01到mynet-tomcat01的互聯呢?可以使用docker network connect命令
然后查看mynet得詳細信息,可以發現聯通之后就是將tomcat01的放入mynet網絡中,也就實現了一個容器兩個ip,類似于阿里云的公網IP和私網IP,都是可以訪問
聯通后我們再次ping連接測試,成功ping通!
實戰:部署Redis集群
# 自定義一個網絡 [root@zsr ~]# docker network create redis --subnet 172.38.0.0/16 92f7a807fc739e3eb7b6e56df5a1c6bc3e701e0a61a544f04e7a2e549538ad20# 通過腳本創建6個redis配置 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 # 通過腳本啟動6個容器 for i in `seq 1 6`; \ do \ docker run -d -p 637${i}:6379 -p 1637${i}:16379 --name redis-${i} \ -v /mydata/redis/node-${i}/data:/data \ -v /mydata/redis/node-${i}/conf/redis.conf:/etc/redis/redis.conf \ --net redis --ip 172.38.0.1${i} redis:6.0 redis-server /etc/redis/redis.conf done # 進入redis-1容器 [root@zsr /]# docker exec -it redis-1 /bin/sh # pwd /data # ls appendonly.aof nodes.conf# 配置集群 # 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 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 M: f693f5b7cc515154a532aa5f48ff627d2827e205 172.38.0.11:6379slots:[0-5460] (5461 slots) master M: b233e1c2053a77c2351b511e784579cd50a3e5a8 172.38.0.12:6379slots:[5461-10922] (5462 slots) master M: da06f6994fe142969f313fa7c6d8cb94cd1facb7 172.38.0.13:6379slots:[10923-16383] (5461 slots) master S: 944f7e0f2e3082745c2e999470f969d53cd1bdd9 172.38.0.14:6379replicates da06f6994fe142969f313fa7c6d8cb94cd1facb7 S: eaab096391c79d4d3d42be66fcc66cb2d724720b 172.38.0.15:6379replicates f693f5b7cc515154a532aa5f48ff627d2827e205 S: 09ba78c0f4f1848a6a9c6d0b9ccc42a159a394a4 172.38.0.16:6379replicates b233e1c2053a77c2351b511e784579cd50a3e5a8 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join . >>> Performing Cluster Check (using node 172.38.0.11:6379) M: f693f5b7cc515154a532aa5f48ff627d2827e205 172.38.0.11:6379slots:[0-5460] (5461 slots) master1 additional replica(s) S: 944f7e0f2e3082745c2e999470f969d53cd1bdd9 172.38.0.14:6379slots: (0 slots) slavereplicates da06f6994fe142969f313fa7c6d8cb94cd1facb7 M: da06f6994fe142969f313fa7c6d8cb94cd1facb7 172.38.0.13:6379slots:[10923-16383] (5461 slots) master1 additional replica(s) S: eaab096391c79d4d3d42be66fcc66cb2d724720b 172.38.0.15:6379slots: (0 slots) slavereplicates f693f5b7cc515154a532aa5f48ff627d2827e205 S: 09ba78c0f4f1848a6a9c6d0b9ccc42a159a394a4 172.38.0.16:6379slots: (0 slots) slavereplicates b233e1c2053a77c2351b511e784579cd50a3e5a8 M: b233e1c2053a77c2351b511e784579cd50a3e5a8 172.38.0.12:6379slots:[5461-10922] (5462 slots) master1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.# 連接集群查看信息 # redis-cli -c 127.0.0.1:6379> cluster info # 查看集群信息 cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:461 cluster_stats_messages_pong_sent:454 cluster_stats_messages_sent:915 cluster_stats_messages_ping_received:449 cluster_stats_messages_pong_received:461 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:915 127.0.0.1:6379> cluster nodes # 查看集群節點信息,三主三從 f693f5b7cc515154a532aa5f48ff627d2827e205 172.38.0.11:6379@16379 myself,master - 0 1613876713000 1 connected 0-5460 944f7e0f2e3082745c2e999470f969d53cd1bdd9 172.38.0.14:6379@16379 slave da06f6994fe142969f313fa7c6d8cb94cd1facb7 0 1613876713071 3 connected da06f6994fe142969f313fa7c6d8cb94cd1facb7 172.38.0.13:6379@16379 master - 0 1613876714675 3 connected 10923-16383 eaab096391c79d4d3d42be66fcc66cb2d724720b 172.38.0.15:6379@16379 slave f693f5b7cc515154a532aa5f48ff627d2827e205 0 1613876713000 1 connected 09ba78c0f4f1848a6a9c6d0b9ccc42a159a394a4 172.38.0.16:6379@16379 slave b233e1c2053a77c2351b511e784579cd50a3e5a8 0 1613876715175 2 connected b233e1c2053a77c2351b511e784579cd50a3e5a8 172.38.0.12:6379@16379 master - 0 1613876713673 2 connected 5461-10922此時我們添加一個鍵值對,可以看到是由172.38.0.13也就是redis-3主機來處理的服務
也就是a的值存在redis-3主機中,那對應的從機應該也有a的值,也就是說如果redis-3服務掛掉,可以從對應的從機中取出a的值
然后再重新獲取a的值,可以看到是從redis-4中取得值,也就是redis-3的從機,實現了高可用,主機掛掉從機自動替代主機
再查看節點的詳細信息,可以看到redis-3主機掛掉,redis-4成為新的主機
十一、SpringBoot微服務&docker
1. 構建springboot項目
首先新建一個springboot項目
然后編寫一個controller,在主程序目錄下新建controller包,其中新建HelloController.java
然后啟動主程序進行測試,訪問localhost:8080/hello,出現如下頁面即成功
2. 打包應用
點擊package進行打包
打包成功后,可以看到生成的target目錄中打包生成的.jar文件
我們用命令行測試一下該jar包能否運行,在其目錄下打開cmd,輸入以下命令
成功啟動代表打包成功
3. 編寫Dockerfile
在項目根目錄下新建Dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]4. 構建鏡像
將編寫好的Dockerfile和打包生成的docker_test-0.0.1-SNAPSHOT.jar文件上傳到服務器
然后用命令構建鏡像
然后便可看到剛生成的鏡像
5. 啟動容器測試
[root@zsr IDEA]# docker run -d -P --name springboot-project first-project 33bbe58ea88c99f0cdc40cda78f04b81c21d48d0dab59c2e9e2896a8899f5cc8 [root@zsr IDEA]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 33bbe58ea88c first-project "java -jar /app.jar …" 4 seconds ago Up 3 seconds 0.0.0.0:49163->8080/tcp springboot-project [root@zsr IDEA]# curl localhost:49163/hello hello[root@zsr IDEA]#根據測試結果,成功啟動項目,訪問的/hello請求返回結果正確
6. 發布鏡像
將鏡像發布至Docker Hub或者阿里云鏡像倉庫,然后別人使用直接pull下來即可運行
總結
以上是生活随笔為你收集整理的从零开始学Docker(超详细讲解+案例分析)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 交通流理论3——交通流三大参数
- 下一篇: 锋利的jquery学习