初始docker

小满三岁啦發表於2024-07-01

image-20240626175723088

前置知識

透過物件導向的知識來了解docker中的映象和容器就很好理解了,docker是C/S架構

  1. 映象:是一個只讀的模板,可以用來建立容器。

  2. 容器:是docker的執行例項,提供了一個獨立的可移植的環境,可以在這個環境中執行應用程式。例項,1個或多個

  3. docker倉庫:用來儲存docker映象的地方,最常用的就是DockerHub

  4. docker daemon: 服務端的守護程序,負責管理伺服器的各種資源。

  5. docker client負責向docker daemon傳送請求, docker daemon收到請求後進行處理,然後將結果返回給docker client。

image-20240622134720076

windows不需要第三方工具連線SSH

# 開啟cmd 執行 mstsc  跟著步驟操作
mstsc

# 開啟cmd 執行 SSH root@伺服器地址  然後輸入密碼即可
SSH root@1.2.3.4

簡單命令

sudo su 切換到超級管理員
exit 切換到普通使用者
cd  回家 root使用者回根目錄 普通使用者回到帶有名字的目錄
mkdir -p /demo/html

mkdir -p是一個Linux命令,用於建立目錄。其中,-p選項表示如果父級目錄不存在,則會自動建立父級目錄。

安裝docker

yum update  # 更新yum倉庫

# 6 安裝
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y

修改映象地址

https://cr.console.aliyun.com/cn-shanghai/instances/mirrors
    
vi /etc/docker/daemon.json

# 儲存並重啟docker
systemctl daemon-reload   # 重新載入docker配置
systemctl restart docker  # 重啟docker

檢視安裝的版本

docker -v
docker --version

啟動和停止

# 啟動 docker
sudo systemctl start docker

# 停止 docker
sudo systemctl stop docker

# 設定開機啟動
sudo systemctl enable docker

# 重啟 docker
sudo systemctl restart docker

# 重新載入 docker 配置
sudo systemctl daemon-reload

# 檢視 docker 內容器的執行狀態
sudo docker stats

# 檢視 docker 概要資訊
sudo docker info

# 檢視 docker 幫助文件
sudo docker --help

檢視全部映象

docker images
docker image ls

run 把映象執行成容器

執行

[sudo] docker run -id --name=centos7 centos:centos7   # 如果不寫版本 預設就是latest
    
   
# id 啟動容器 不進入容器內部
# it 啟動容器 進入容器內部
# --name 起一個別名 別名必須唯一
# centos:centos7 基於哪一個映象去執行

# -i 如果不需要進入容器內部進行互動式輸入命令 那麼 -i是可以省略的

執行的後面也可以跟命令

 sudo docker run -it --name=t1 centos:centos7 sleep 10  # 10秒結束

檢視正則執行的容器

[sudo] docker ps 
[sudo] docker ps -s

檢視全部容器

[sudo] docker ps -a

執行命令 返回命令結果

# 命令
[sudo] docker exec -it <container>  bash


ccsvip@ccsvip-virtual-machine:~$ sudo docker ps -s
CONTAINER ID   IMAGE            COMMAND       CREATED         STATUS         PORTS     NAMES             SIZE

3c889a59ed12   centos:centos7   "/bin/bash"   6 minutes ago   Up 6 minutes             nervous_maxwell   0B (virtual 204MB)
ccsvip@ccsvip-virtual-machine:~$ sudo docker exec -it 3c889a59ed12 bash
    
    
  
# 可以簡寫使用部分id  後面也可以跟上要執行的命令 
[sudo] docker exec -it 3c88 ls

/bin/bash和sh命令

如果 sudo docker exec -it id號 /bin/bash進不去 就試試 sudo docker exec -it id號 sh

啟動已經建立過但是停止了的容器

[sudo] docker start id號或id號簡稱  如果是id號 寫前3位就可以了

停止執行的容器

[sudo] docker stop id或容器名稱

刪除容器 rm

[sudo] docker rm name1 name2  # 刪多個 類似pip
[sudo] docker rm name # 刪單個

name可以是容器的名稱 也可以是 id的名稱

image-20240620152044986

停止全部容器

[sudo] docker stop `sudo docker ps -a -q`
[sudo] docker stop $(sudo docker ps -sq)

刪除非執行狀態的容器

[sudo] docker rm `docker ps -f status=exited`
[sudo] docker rm $(docker ps -f status=exited)

刪除全部容器

[sudo] docker rm `docker -ps -a -q`
[sudo] docker rm $(docker -ps -aq)

# 注  -f 強制刪除 慎用

刪除全部映象

[sudo] docker rmi `docker images -q`
[sudo] docker rmi $(docker images -q)

檢視日誌

docker logs id名或容器名 # 檢視全部日誌
docker logs -f id名或容器名 # 持續檢視最新日誌
docker logs -n 數字  # 檢視最近n條日誌 

-v命令 跟宿主機的檔案做對映

image-20240626010901441

image-20240626012338324

您可以將主機上的目錄或檔案與容器中的目錄或檔案進行關聯,使得容器可以訪問和修改主機上的資料。

# 語法
sudo docker run -it --name=centos7 -v 主機目錄或檔案的路徑:容器的檔案或目錄  centos:centos7

sudo docker run -it --name=centos7 -v /home/小滿:/小滿 centos:centos7
        
# 注意點 容器的目錄 也就是容器:路徑 如果目錄不存在 會自動去建立的。

匿名掛載

docker run -id --name nginx2 -v /usr/share/nginx/html/ -p 80:80 nginx # 注意 如果只寫一個路徑 表示容器的路徑
    
# 所有的掛載都會到 var/lib/docker/volumes/ 這個目錄
root@iZbp1hwoc9gqiqk631pnpfZ:/# ls var/lib/docker/volumes/
293a9827a459f39a380748bae08ababd1ae141e5c745ed155dd3da7bc3ca8880  c4ff0ff27f65ba79917def3f11f6725945b98f223c3a3f880f8faafb529b2fca
3e58f4a97113dd43538c0d30f0ba58ee9a8e45a755dce1e7ca3b401f58c286a3  c5ad942882fe21f4212bb8523205d0fde58c616088ae794b213df021acc56b30
79fa4e6cc3ae3bfafa38d2e0400c5b1785a3d4966bc62806cd00d2589793201b  ef8bc9828f671d4e5d394cd55d064db37125ad4caa4c9b8882a6b89451280acb
backingFsBlockDev                                                 metadata.db


# 透過 docker inspect id或者名稱能查詢到掛載資訊
"Mounts": [
    {
        "Type": "bind",
        "Source": "/data",
        "Destination": "/abc/123",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }

掛載許可權 :ro只讀 :rw讀寫

sudo docker run -it --name=centos7 -v /home/小滿:/小滿:ro centos:centos7  # 只讀模式 容器內部只能檢視無法操作
            
sudo docker run -it --name=centos7 -v /home/小滿:/小滿:rw centos:centos7  # 讀寫模式 容器內部可以修改新增

繼承 --volumes-from

#容器 centos7-01 指定目錄掛載
docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
#容器 centos7-04 和 centos7-05 相當於繼承 centos7-01 容器的掛載目錄
docker run -di --volumes-fn centos7-01--name centos7-04 centos:7docker run -di --volumes-fm centos7-01 --name centos7-05 centos :7

檢視目錄卷的掛載關係

埠對映

執行一個MySQL容器做埠對映,需要安裝 net-tools

根據搜尋結果,你的命令是在 Docker 中執行一個 MySQL 5.7 容器,並將容器的 3306 埠對映到主機的 3308 埠。命令如下所示:

[sudo] docker run -id --name=mysql5.7 -p 3308:3306 -e MYSQL_ROOT_PASSWORD=xm123 mysql:5.7

這個命令的含義是:

  • sudo docker run:執行一個 Docker 容器。
  • -id:以互動模式和後臺執行的方式啟動容器。
  • --name=mysql5.7:給容器指定一個名稱為 "mysql5.7"。
  • -p 3308:3306:將容器的 3306 埠對映到主機的 3308 埠。
  • -e MYSQL_ROOT_PASSWORD=xm123:設定 MySQL 的 root 使用者密碼為 "xm123"。
  • mysql:5.7:使用 MySQL 5.7 映象建立容器。

這個命令的目的是在 Docker 中建立一個 MySQL 5.7 容器,並透過埠對映使其可以透過主機的 3308 埠訪問。容器的名稱為 "mysql5.7",MySQL 的 root 使用者密碼設定為 "xm123"。

注意:宿主連線的地址應該為:mysql -h ipaddr得到的地址 -P 3308 -uroot -p

隨機埠對映 -P

[sudo] docker run -d -P imagesname

[sudo] docker ps 可以檢視埠

對映多個埠

[sudo] docker run -d -p 8000:5000 -p 8001:5000 image-name

-e 設定環境變數

image-20240626014554927

docker run -d --name mysql -v ./mysqldata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xm123 -p 3308:3306 mysql:5.7

重啟重啟策略 一般是設定 always

image-20240626015754074

docker run --name nginx-test -d -P --restart always  nginx  # 這樣設定 --restart always 就可以自動重啟了

# 上面這種情況,如果是執行在虛擬機器,虛擬機器重啟可以模擬
# 如果執行在伺服器,使用systemctl restart docker  重啟docker 可以模擬。

image-20240626020035908

net-tools

# 安裝
sudo apt install net-tools

yum install net-tools


# 檢視埠使用情況
sudo netstat -nlp | grep 3308 # 埠號
netstat -nlp | grep 3308

image-20240620185239361

如果docker停止了,那麼服務就連不上了

# docker
ccsvip@ccsvip-virtual-machine:/home$ sudo docker stop mysql5.7
mysql5.7


# 宿主機
C:\Users\chuxu>mysql -h 192.168.147.128 -P 3308 -uroot -p
Enter password: *****
ERROR 2003 (HY000): Can't connect to MySQL server on '地址:3308' (10061)

ubuntu、debian 更新以及安裝

mysql容器的底層作業系統是debian。debian系和ubuntu屬於統一分支

[sudo] apt-get update # 更新

[sudo] apt install xxx # 安裝

[sudo] apt install vim -y  # -y 無需手動確認

檔案複製 在宿主機執行 cp

順序說明: 冒號右邊是目標地址 冒號左邊是原始地址

docker cp <宿主機檔案路徑> <容器名稱或ID>:<容器目標路徑>
[sudo] docker cp ./1.txt python:/   # 把宿主機的1.txt 複製到容器的根目錄
    
    
docker cp <容器名稱或ID>:<容器檔案路徑> <宿主機目標路徑>
[sudo] docker cp python:/cancer ./  # 將容器根目錄下的 cancer資料夾(含內部檔案)複製到宿主機的當前資料夾

映象不含前臺程序,進入操作 --rm

docker run -ti -rm book bash

docker run:執行一個新的Docker容器。
-ti:使用互動式終端和終端的偽終端。
--rm:容器退出後自動刪除容器。這可以確保容器在退出後不會佔用磁碟空間。
book:指定要使用的映象。
bash:在容器中執行的命令,這裡是一個互動式的bash終端。

容器其他操作

image-20240626020520571

映象詳細資訊

docker image inspect mysql:5.7

image-20240626021359732

檢視容器內程序

docker top 容器名稱或id
root@iZbp1hwoc9gqiqk631pnpfZ:~/project# docker top mysql

image-20240626021135232

檢視容器的ip地址

[sudo] docker inspect 容器名稱或id

# 返回的結果是一個json格式的內容

image-20240620193925189

獲取ip地址 容器一定要是開啟狀態!

ccsvip@ccsvip-virtual-machine:/home$ sudo docker inspect mysql5.7 --format="{{.NetworkSettings.IPAddress}}"
172.17.0.2

容器之間互相ping

apt-get update
apt-get install iputils-ping

ping 地址

資料卷相關操作

image-20240626145747614

設定資料卷

檢視容器具體資訊,就可以知道掛載到哪一個目錄了

docker inspect nginx-test
# 執行後 找到 Mounts
"Mounts": [
    {
        "Type": "volume",  # 型別資料卷
        "Name": "nginx-html", # 名稱
        "Source": "/var/lib/docker/volumes/nginx-html/_data",  # 宿主機目錄
        "Destination": "/usr/share/nginx/html",  # 容器內的目錄
        "Driver": "local",
        "Mode": "z",
        "RW": true,  # 可讀可寫
        "Propagation": ""
    }
],

檢視全部資料卷 docker volume ls

image-20240626142835485

檢視某個資料卷的詳細資訊 docker volume inspect 容器名稱或id

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker volume inspect nginx-test
[
    {
        "CreatedAt": "2024-06-26T14:22:18+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginx-test/_data",
        "Name": "nginx-test",
        "Options": null,
        "Scope": "local"
    }
]

建立資料卷 docker volume create 資料卷名稱

預設會建立在/var/lib/docker/volumes/volume_test/_data"這個目錄。

這樣不論在宿主機容器內,修改內容都是會同步的,後續即便刪除了容器內容也是還在的。

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker volume create volume_test
volume_test
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker volume inspect volume_test
[
    {
        "CreatedAt": "2024-06-26T14:33:14+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/volume_test/_data",
        "Name": "volume_test",
        "Options": null,
        "Scope": "local"
    }
]

刪除資料卷 docker volume rm 資料卷名稱或id

注意,正在執行的容器掛載的資料卷無法直接刪除,可以刪除容器後再刪除資料卷。

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker volume rm volume_test
volume_test

應用部署

mysql部署

image-20240626163436877

/var/lib/mysql -e MYSQL_ROOT_PASSWORD=

/var/lib/mysql  備份路徑
MYSQL_ROOT_PASSWORD  設定root密碼
#0 dokcer 中部署mysql,以後不需要在宿主機上裝mysql
	

#1  沒有做目錄對映---》配置檔案--》表資料都在容器中---》一旦刪除--》所有都沒了
docker run -di --name=mysql -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7


# 2 做目錄(配置檔案和資料檔案)和埠對映

# 做目錄對映:data檔案,配置檔案
# 建立資料夾
mkdir /mysql
mkdir /mysql/conf.d
mkdir /mysql/data/
vi /mysql/my.cnf
[client]
default-character-set=utf8
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000

docker run  -di -v /mysql/data/:/var/lib/mysql -v /mysql/conf.d:/etc/mysql/conf.d -v /mysql/my.cnf:/etc/mysql/my.cnf -p 3306:3306 --name mysql5.7 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7      
        
     
    
# 建立庫,建立表,插入資料

# 關閉容器,刪除容器,myslq的容器沒了,但是資料在宿主機上放著
 docker stop mysql2
 docker rm mysql2
##docker rm mysql -f  容器之間刪了

# 再執行起一個容器,做好目錄對映,資料都回來了
docker run  -di -v /mysql/data/:/var/lib/mysql -v /mysql/conf.d:/etc/mysql/conf.d -v /mysql/my.cnf:/etc/mysql/my.cnf -p 3307:3306 --name mysql2 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 



# 補充  -e引數--》環境變數
	-不同映象提供不同引數
    -傳入後放入環境變數
    echo $MYSQL_ROOT_PASSWORD
	

這些檔案是用於組織和儲存容器內部的檔案和目錄的。以下是對這些檔案的簡要說明:

  • bin:包含可執行檔案(二進位制檔案)的目錄,用於存放一些基本的系統命令和工具。
  • boot:包含啟動相關的檔案,如核心和引導載入程式。
  • dev:包含裝置檔案,用於與主機系統進行互動。
  • docker-entrypoint-initdb.d:如果你的容器是MySQL,這個目錄用於存放初始化資料庫的指令碼。
  • entrypoint.sh:如果你的容器有自定義的入口指令碼,它可能會存放在這個檔案中。
  • etc:包含系統配置檔案的目錄,如網路配置、軟體配置等。
  • home:使用者的主目錄,用於存放使用者的個人檔案和配置。
  • lib:包含共享庫檔案的目錄,這些庫檔案被可執行檔案使用。
  • lib64:類似於lib目錄,但用於64位系統。
  • media:用於掛載可移動介質(如CD、DVD、USB驅動器)的目錄。
  • mnt:用於掛載其他檔案系統的目錄。
  • opt:用於存放可選軟體包的目錄。
  • proc:虛擬檔案系統,提供有關係統程序的資訊。
  • root:root使用者的主目錄。
  • run:用於存放執行時檔案的目錄,如PID檔案和鎖檔案。
  • sbin:包含系統管理員使用的系統命令和工具。
  • srv:用於存放服務相關的資料和檔案。
  • sys:虛擬檔案系統,提供有關係統硬體和核心的資訊。
  • tmp:用於存放臨時檔案的目錄。
  • usr:包含使用者安裝的應用程式和檔案的目錄。
  • var:包含可變資料的目錄,如日誌檔案、資料庫檔案等。

如果你想將宿主機的檔案與容器共享,你可以使用-v選項將宿主機的目錄掛載到容器的相應目錄中。例如,你可以將宿主機的MySQL資料目錄掛載到容器的/var/lib/mysql目錄,將配置檔案掛載到/etc/mysql/conf.d目錄。

redis部署

image-20240626164459756

#1  拉取redis映象
docker pull redis  #最新
mkdir /root/data
vim /root/redis.conf

bind 0.0.0.0           
daemonize NO
protected-mode yes
requirepass 123456 


bind 0.0.0.0:這句程式碼指定Redis監聽所有可用的網路介面,允許從任意IP地址訪問Redis伺服器。
daemonize NO:這句程式碼指定Redis以非守護程序的方式執行,即在前臺執行而不是作為後臺程序。
protected-mode yes:這句程式碼啟用Redis的保護模式,該模式會限制對Redis的遠端訪問,只允許本地訪問。
requirepass xm123:這句程式碼設定Redis的訪問密碼為"xm123",需要在連線Redis時提供正確的密碼才能進行操作


# 執行
#啟動容器時,執行的命令是什麼 redis-server /etc/redis/redis.conf

docker run -id  -p 6379:6379 --name redis -v /root/redis.conf:/etc/redis/redis.conf -v /root/data:/data redis  redis-server /etc/redis/redis.conf
       
    
# 在容器執行時,可以自己定製執行命名 舉例:docker run -id centos:centos7 ls

            
     
    
# 遠端連結redis操作

nginx部署

  • /etc/nginx/:NGINX的配置檔案通常位於此目錄中。
  • /usr/share/nginx/:NGINX的靜態資原始檔(如HTML、CSS、JavaScript檔案)通常位於此目錄中。
  • /var/log/nginx/:NGINX的日誌檔案通常位於此目錄中。
# 拉取nginx映象
docker pull nginx

# run起容器
# docker run -id --name nginx -p 80:80 nginx
    
# /usr/share/nginx/html
docker run -id --name nginx1 -p 8008:80 -v /root/html:/usr/share/nginx/html nginx
# 以後只需要修改宿主機的/root/html 路徑,看到頁面就是修改後的

docker網路

建立網路後可以直接透過網路名稱取

image-20240626173657020

建立網路 docker network create 網路名

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker network create blog_network
8ed8ce47e1d39c84f05d2614ddaeb86b69e2453d4520ca4076d456121af9f584

列出所有網路 docker network ls

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker network ls
NETWORK ID     NAME                       DRIVER    SCOPE
dbaa99745700   1panel-network             bridge    local
8ed8ce47e1d3   blog_network               bridge    local
4c2ef89812cb   bridge                     bridge    local
068181900e56   docker-compose-luffy_web   bridge    local
3058fcd56838   host                       host      local
796d81083b6b   none                       null      local
d39ef21c7b10   project_default            bridge    local

將容器加入網路docker network connect 網路名稱 容器名稱

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker network connect blog_network nginx-html
root@iZbp1hwoc9gqiqk631pnpfZ:~#

檢視網路 docker network inspect 網路名稱或網路id

Containers中的 Name 就是加入到該網路的容器。

image-20240626173351311

加入網路後容器之間可以互相ping 也可以run的時候直接寫容器名稱

image-20240626173303226

刪除網路 docker network rm 網路名稱或網路id

docker network rm test_network

image-20240626173817959

將容器儲存為物件

檢視映象

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
centos       centos7   eeb6ee3f44bd   2 years ago     204MB

啟動容器,並寫入一些內容

docker run -id --name centos centos:centos7

docker exec -it centos /bin/bash

yum update -f

yum install vim

vim cancer.txt 

寫入一些內容在裡面

exit 退出

製作成映象

docker commit centos centos_with_vim  

# 解釋  docker commit 容器名稱 打包後的映象名稱:[tag 可選]

docker commit -a "cancer" -m "centos7+tomcat" mycentos mycentos:7
  • docker commit:這是Docker命令,用於建立一個新的映象。
  • -a "cancer":這是docker commit命令的選項之一,用於指定作者的資訊。在這個例子中,作者被設定為"cancer"。
  • -m "centos7+tomcat":這是docker commit命令的選項之一,用於指定提交的訊息。在這個例子中,提交訊息被設定為"centos7+tomcat"。
  • mycentos:這是要建立映象的容器的名稱或ID。在這個例子中,容器名稱為"mycentos"。
  • mycentos:7:這是新映象的名稱和標籤。在這個例子中,新映象被命名為"mycentos",並帶有標籤"7"。

再次啟動容器 檢視內容

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run -it --name centos centos_vim
[root@6c4dea98675f /]# ls
anaconda-post.log  bin  cancer.txt  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@6c4dea98675f /]# cat cancer.txt 
xm is beautiful
i think this is a good girl!!

本地映象推送給到docker hub

https://hub.docker.com/

image-20240621162105498

image-20240621162140517

執行命令docker tag id名字或者映象名字 然後是下面紅框的名字:[可選標籤]

執行命令 docker pull xxx 這裡的xxx就是

image-20240621163851633

docker pull cancerwake/docker_vim:v1

映象備份和恢復

  • i input
  • o output

備份

docker save -o 結果 映象名稱

# 例如
docker save -o centos_vim.tar centos_demo

恢復

docker load -i 映象名稱

# 例如
docker load -i centos_vim.tar  

image-20240621170509174

dockerfile

注:執行run後面跟的命令優先順序是高於內部cmd命令的

注:CMD和ENTRYPOINT指令是容器執行時候生效,其他指令都是容器構建時候生效。

概念

Dockerfile是一個文字檔案,裡面包含了一條條的指令,用老告訴docker如何來構建映象,這個映象中包括了我們應用程式執行的所有命令,各種依賴,配置環境,和應用程式所需要的所有內容,一般來說包括下面這些內容:

  1. 精簡版的作業系統,比如Alpine
  2. 應用程式執行時的環境,比如NodeJS python java
  3. 應用程式,比如django 或者SpritBoot打包好的jar包
  4. 應用程式的第三方依賴庫或者包
  5. 應用程式的配置檔案、環境變數等。

一般來說,我們會在專案根目錄下建立一個Dockerfile檔案,在這個檔案中寫入構建映象,所需要的各種指令之後,docker就會根據這個Dockerfile檔案來構建一個映象,有了這個映象之後就可以使用這個映象來建立容器,然後在容器中執行應用程式。

image-20240622140009026

# 1 基礎映象

# 我們需要先指定一個基礎映象
# 映象是按層次結構來構建的,每一層都是基於上一層的。
# 所以我們需要先指定一個基礎映象,在這個基礎映象上新增我們的應用程式。

# 2 配置完映象後,還需要把應用程式複製映象中,  --> copy 源路徑 目標路徑
# 源路徑:相對於Dockerfile檔案的路徑
# 目標路徑:目標路徑是相對於映象的路徑

# 3 在映象中執行程式 可以使用CMD命令
# 注意引號是雙引號 CMD ["node", "index.js"]  方括號第一個引數代表可執行程式的名字 後面的代表引數
# 也可以寫成CMD node /index.js 

# 4 構建映象
# 方式1: docker build -t="name" .
# 方式2: docker build -t name .
# 案例中  docker build -t hello-docker .

FROM ubuntu:latest  # FROM 基礎映象 基於哪一個映象去構建

LABEL maintainer="your-name@example.com"   # LEBAL 宣告後設資料標籤
LABEL version="1.0"
LABEL description="This is a sample Docker image."

WORKDIR /app # 工作目錄 如果沒有會建立出來 相當於 mkdir 然後cd進去 後面的RUN命令都是在定義的這個目錄下去執行

RUN apt-get update && apt-get install -y \  # 命令 後面跟上Linux命令 是dockerfile的核心
    python3 \
    python3-pip

COPY requirements.txt .  # 將宿主機的檔案 複製到映象內
RUN pip3 install -r requirements.txt

COPY . .

CMD ["python3", "app.py"]  # 執行CMD命令

image-20240314104516220

image-20240626194318423

image-20240623040727746

image-20240623040704342

CMD 和 ENTRYPOINT的區別

https://www.cnblogs.com/littlecc/p/17419047.html

image-20240623041040369

run後面的命令是可以覆蓋CMD命令的

# 正常的輸出 
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run hello:1.0
hello world

# 覆蓋CMD命令
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run hello:1.0 echo "hello xm"
hello xm

--no-cache

構建一個沒有快取的映象
使用場景,比如你在Dockerfile裡面寫了一個 RUN git clone xxx 這樣就需要加上 --no-cache

docker build -t book . -f Dockerfile --no-cache

CMD兩種方式的區別 [] 這種不會解析環境變數

image-20240626195426367

下面這種則能解析環境變數 值得一提的是 ,環境變數 設定加不加引號都是可以的。

ROM centos:centos7
ENV CONTENT=海月  # 這樣也是可以的
CMD echo $CONTENT

image-20240626200020537

因為能使用環境變數 所以run的時候能動態修改值

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run -e CONTENT=大喬  hello:5.0
大喬

WORKDIR 注意 相當於mkdir 然後cd 進入

根據搜尋結果,Dockerfile中的WORKDIR指令用於設定工作目錄。每個WORKDIR指令都會更改容器中的當前工作目錄。在你提供的Dockerfile中,有三個連續的WORKDIR指令:

WORKDIR /a
WORKDIR b
WORKDIR c

這意味著容器的當前工作目錄將被設定為/a,然後在此基礎上建立一個名為b的子目錄,最後在b目錄中建立一個名為c的子目錄。因此,當你執行容器並執行pwd命令時,輸出將是/a/b/c

image-20240626202219266

如果WORKDIR執行時父目錄不存在也會自動建立

root@iZbp1hwoc9gqiqk631pnpfZ:~# cat helloworld
FROM centos:centos7
WORKDIR /a/b/c/d/e
CMD pwd
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run test:1.0
/a/b/c/d/e

WORKDIR引用環境變數

image-20240626203400617

RUN 命令

image-20240626203709744

image-20240626204254208

思考:為什麼執行的時候修改環境變數的值結果沒有發生變化

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run -e NAME=阿珂  test:9.0
小滿最棒啦


# 因為執行時機問題
# 在執行容器時使用-e選項來設定環境變數時,它會覆蓋Dockerfile中設定的預設值。因此,即使在執行容器時設定了NAME=阿珂,但在Dockerfile中設定的預設值小滿最棒啦仍然會被使用。

ADD

image-20240626210046890

需求如下:

image-20240626210141247

程式碼實現

# 程式碼地址
https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.25/bin/apache-tomcat-10.1.25.tar.gz
    
FROM nginx
WORKDIR /app
COPY dist.tar.gz .
RUN tar -xvzf dist.tar.gz
RUN cp -r dist/* /usr/share/nginx/html
ENTRYPOINT ["nginx", "-g", "daemon off;"] # 別忘記分號

# 注意 cp -r的時候 複製的是資料夾內的內容 不會複製當前資料夾

ENTRYPONIT

image-20240627195739896

關於 . 的理解

image-20240623165752348

image-20240623165938347

dockerfile案例-1

image-20240626192116718

構建一個容器 一執行就列印helloworld

# 1. 建立一個檔案  其實就是Dockerfile
vim hellworld

# helloworld內容
FROM centos:centos7
CMD ["echo", "hello world"]

# 構建  在當前目錄下查詢helloworld Dockerfile 去構建名稱為helloworld的映象 
# -t 可以指定映象名稱和標籤
docker build -t helloworld . -f helloworld

# 執行映象
docker run helloworld

image-20240626192506525

dockerfile案例0

// index.js內容
console.log("你好,我是小滿,我正在學習docker!")

// Dockerfile內容
FROM node:14-alpine
COPY  index.js /index.js
CMD ["node", "index.js"]

// docker build -t hello-docker .

// docker run hello-docker

image-20240622143323191

dockerfile案例1

1 在宿主機新建一個Dockerfile 寫一些內容

Dockerfile 沒有字尾 只能交這個名字


FROM centos
ENV name 小滿
ENV age 3
RUN mkdir data
RUN echo "print(True)" > /data/result.py
RUN echo $name
RUN echo $age
WORKDIR data

2 宿主機構建

docker build -t="映象的名字" .   # 別忘記 .  它的意思就是在當前目錄下找。  

3 構建成功後 進入容器檢視結果

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker build -t="demo" .
                                                                                             0.0s
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker images
REPOSITORY        TAG       IMAGE ID       CREATED             SIZE
demo              latest    43eefa559286   14 seconds ago      917MB

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run -id --name demo1 demo
85831a56a21939558f35349272d9b62c80718153e89e5f11163e1c5828e7932e

root@iZbp1hwoc9gqiqk631pnpfZ:~# docker exec -it demo1 /bin/bash
root@85831a56a219:/data# ls
result.py

root@85831a56a219:/data# python result.py 
True

dockerfile案例2

1 在宿主機新建一個Dockerfile

FROM python
ENV name 小滿
ENV age 3
RUN mkdir /data
RUN echo "input()" > /data/result.py
RUN echo $name
RUN echo $age
WORKDIR /data
CMD ['python', './result.py']  # 執行容器時會預設加上 /bin/sh -c

2 宿主機構建

docker build -t="demo" .

3 構建成功後 進入容器檢視結果

# 錯誤示範
docker run -id --name demo demo
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker logs demo
/bin/sh: 1: [python,: not found
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS                            PORTS     NAMES
cb525bf6f078   demo      "/bin/sh -c '['pytho…"   About a minute ago   Exited (127) About a minute ago             demo
             
             # 注意 COMMAND 部分
             
             
            
 # 最佳化後的示範
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker run -id --name demo demo python /data/result.py

root@c898485f5a7f:/data# ls
result.py
root@c898485f5a7f:/data# python
Python 3.10.1 (main, Dec 21 2021, 09:01:08) [GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getenv("age")
'3'
>>> exit()
root@c898485f5a7f:/data# exit
exit
root@iZbp1hwoc9gqiqk631pnpfZ:~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS     NAMES
c898485f5a7f   demo      "python /data/result…"   About a minute ago   Up About a minute             demo
             
             # COMMAND 部分已被修改了

Dockerfile 上線django專案(前後端結合)

# Dockerfile內容如下
FROM python
WORKDIR /book
COPY . .
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD ["python", "manage.py", "runserver", "0.0.0.0:8888"]

# 製作映象命令如下
docker build -t django_demo . -f Dockerfile

# 啟動命令如下
docker run -d -p 8888:8888 -v /root/django_test/:/book django_demo
        
# 上線的時候發現post請求沒有註釋掉csrf中介軟體,於是在宿主機中解決,容器內自動修改。

邏輯卷

docker容器有一個特點,容器中的資料是不會持久化的,當我們建立一個容器的時候,通常以一個乾淨的檔案系統開始。容器啟動之後我們可以在容器中建立檔案,修改檔案,但是容器停止之後,容器中的所有資料都會丟失掉,如果我們想要持久化容器中的資料應該怎麼做呢?邏輯卷就是用來解決這個問題的。它可以把容器中的目錄或者指定路徑對映到宿主機的某個目錄或者位置上,這樣就可以將資料儲存到宿主機的磁碟上,實現了資料的持久化。

實際上我們的容器就好像是一個簡易版的作業系統,只不過系統中只安裝了我們的程式執行所需要的環境,前邊說到我們的容器是可以刪除的,那如果刪除了,容器中的程式產生的需要持久化的資料怎麼辦呢?容器執行的時候我們可以進容器去檢視,容器一旦刪除就什麼都沒有了。
所以資料卷就是來解決這個問題的,是用來將資料持久化到我們宿主機上,與容器間實現資料共字,簡單的說就是將宿主機的目錄對映到容器中的目錄,應用程式在容器中的目錄讀寫資料會同步到宿主機上,這樣容器產生的資料就可以持久化了,比如我們的資料庫容器,就可以把資料儲存到我們宿主機上的真實磁碟中。

映象分層

每一個Dockerfile命令都會構建一層映象(本質上是每一層都會啟動一個容器,執行完命令後,將容器進行提交,透過檢視下載下來的映象,發現歷史層資訊的層ID是missing,其實是因為原本的層id只存在於構建映象的宿主機上,一旦轉移映象後,歷史層訊息中將只保留最新一層的ID


# 只要執行一個命令就會多一層
RUN yum install vim -y
RUN yum install git -y


# 檢視映象分層的命令
docker history  liuqingzheng/lqz_books:v1
# 好處:
構建快,分發方便,如果本地有某一層了,這一層就不需要下載了


# 補充:Dcokerfile寫命令,建議多條命令合為一條---》只會生成一層
RUN python -m pip install --upgrade pip &&\
python -m pip install --upgrade setuptools &&\
pip install -r requirements.txt

私有倉庫 registry

1 拉取映象

docker pull registry

2 修改配置檔案

vim etc/docker/daemon.json 
{
  "registry-mirrors": ["https://ykibxgcr.mirror.aliyuncs.com"],
  "insecure-registries": ["47.99.96.180:5000"]  # 增加這個 ip 地址根據實際填寫
}

3 重新載入配置

[sudo] systemctl daemon-reload

4 重啟docker

[sudo] systemctl restart docker

5 建立私有倉庫

docker run -id --name registry -p 5000:5000 -v /data/:/abc/data registry

6 執行私有倉庫

http://47.99.96.180:5000/v2/_catalog

地址寫你自己的伺服器地址,如果看到下圖所示,就表示建立成功了。

image-20240623173453989

7 推送到私有倉庫

# 給映象打一個標籤
docker tag hello-world:latest hello-world:v1
        
# 推
docker push hello-world:v1

docker compose

注意:

  1. 老版本要寫version,新版本不需要
  2. 老版本要單獨安裝docker-compose,新版本docker自帶docker-compose
  3. docker-compose中不需要定義容器名稱,直接使用服務名稱名稱就可以訪問同一個網路了。
  4. 如果要使用自己建立的資料卷,需要指定external: true

image-20240627212440867

docker compose是由docker compose官方開源的專案,是一個定義和執行多個docker容器應用程式的工具,比如前後端分離的專案,這些服務都是彼此獨立的但是又是相互有關聯的,需要配合來完成工作,前端需要連線後端,後端需要連線資料庫等。

這些服務之間的關聯關係,就是docker compose要解決的問題。

它透過一個單獨的docker-compose.yaml的配置檔案,將這一組互相關聯的容器組合在一起,形成一個專案,然後使用一條命令就可以啟動,停止,或重建這些服務。

需要注意的是:編寫的docker-compose.yaml命令之間,一定要有空格,不然會報錯。

image-20240622144700222

image-20240622144915067

image-20240627202509679

image-20240627210826843

資料卷注意

image-20240627211424039

docker-compose常用命令

命令 描述
docker-compose up 會自動搜尋當前路徑下的docker-compose.yml檔案並啟動容器。
docker-compose -f up 指定檔案啟動容器。
docker-compose up -d 以後臺模式執行,不會在終端輸出日誌。
docker-compose stop 停止容器,但不會刪除容器和映象。
docker-compose down 停止容器,並刪除關聯的容器。
docker-compose start 啟動docker-compose.yml檔案中管理的容器。
docker-compose ps 顯示正在執行的容器。
docker-compose images 顯示docker-compose管理的映象。
docker-compose exec /bin/bash 進入到docker-compose.yml檔案中指定的服務容器內部。
docker-compose up -d --build 啟動容器並重新構建映象,基於重新構建的映象啟動。

使用步驟

# 檢視核心命令 arch
# 去下載對應的版本 https://github.com/docker/compose/releases
# 下載lrzsz 然後透過rz命令上傳到伺服器上
# 透過cp命令複製到 usr/local/bin/ 目錄,因為該目錄是環境變數所在的目錄。
# 修改許可權, 新增可執行許可權  chmod +x usr/local/bin/docker-compose

透過docker-compose部署flask專案

2個容器,1個redis 1個flask

建立需要部署的專案

app.py
Dockerfile
requirements.txt
# app.py
from flask import Flask
from redis import Redis

app = Flask(__name__)

# 之前的寫法 decode_responses 的意思是 使用utf-u去解碼
# redis = Redis("127.0.0.1", port=6379, decode_responses=True)
redis = Redis(host="redis", port=6379, decode_responses=True)  # 容器的主機名 --> flask容器和redis容器是能ping通的, 可以透過ip ping 也可以透過主機名 ping


@app.route("/")
def index():
    redis.incr("hits")  # 對名為"hits"的鍵進行自增操作
    return f"這是您第{redis.get('hits')}次訪問本站。"


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port="5001")
# Dockerfile
FROM python
WORKDIR /app
COPY . .
RUN pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
EXPOSE 5001
CMD [ "python", "app.py" ]

編寫docker-compose.yaml

# version: '3'  版本不需要寫
services:
  redis:
    image: "redis"  # image 代表映象的名稱
    volumes:
      - /data:/data
  web:
    build:   # build表示構建映象 這裡的意思是在當前資料夾下找Dockerfile檔案去構建映象
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:5001  # 埠對映 宿主機:容器
  
    environment:
      - REDIS_HOST=redis  # 從環境變數裡面取值 就是之前的 -e 引數
    volumes:
      - /data:/data  # 新增目錄對映 即便容器刪了 資料也不會丟失 主要是資料庫的資料

執行命令 開始部署

docker-compose up  # 前臺執行
docker-compose up -d # 後臺執行

透過多執行緒訪問測試

import requests
from concurrent.futures import ThreadPoolExecutor


def run():
    requests.get("http://47.99.96.180:8080/")
    
    
if __name__ == "__main__":
    pool = ThreadPoolExecutor(max_workers=20)
    for index in range(20000):
        pool.submit(run)
    pool.shutdown()

image-20240624185141803

檢視正在執行的docker-compose容器

注意,需要在docker-compose.yaml檔案同目錄中輸入命令才可以,不然會報錯no configuration file provided: not found

image-20240624190113903

相關文章