Docker構建鏡像


一、概念

1、基於容器生成鏡像

通過 docker commit 命令將現有的容器提交來生成新的鏡像。
原理:容器啟動后的修改都保存在可寫層,通過對可寫層的修改生成新的鏡像。

[root@hqs docker-hello]# docker commit --help
Usage:  docker commit [OPTIONS選項] CONTAINER容器 [REPOSITORY倉庫名[:TAG標簽]]
Create a new image from a containers changes
Options:
  -a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")    # 指定作者
  -c, --change list      Apply Dockerfile instruction to the created image             # 允許使用dockerfile的指令
  -m, --message string   Commit message                                  # 提交信息
  -p, --pause            Pause container during commit (default true)    # 創建鏡像過程中容器暫停(掛起)
  
 
# 操作流程:運行容器——》修改容器——》容器保存為新的鏡像
# 案例:
# 1.運行容器
[hqs-docker@hecs-hqs-01 tester03]$ docker run -ti centos /bin/bash
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
a1d0c7532777: Pull complete 
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
# 2.修改容器
[root@69b728ed9a9b yum.repos.d]# rm -rf Cent*
[root@69b728ed9a9b yum.repos.d]# vi nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
[root@69b728ed9a9b yum.repos.d]# yum install -y nginx
[root@69b728ed9a9b yum.repos.d]# exit
# 3.保存為新的鏡像
[hqs-docker@hecs-hqs-01 tester03]$ docker commit 69b728ed9a9b centos-with-nginx
sha256:192cee469ee07eee42d653d65239eff8474d34f359b9431221e341f1e704587d
# 4.啟動新容器
[hqs-docker@hecs-hqs-01 tester03]$ docker run -dti centos-with-nginx
0b76bde1cb0f2bbc363541b2f85765d45ae1b0b343ca81af31552fce711fe5b7
[hqs-docker@hecs-hqs-01 tester03]$ docker exec -ti 0b76bde /bin/bash
[root@0b76bde1cb0f /]# find / -name nginx
/usr/share/nginx
/usr/sbin/nginx
/usr/libexec/initscripts/legacy-actions/nginx
/usr/lib64/nginx
/etc/logrotate.d/nginx
/etc/nginx
/var/log/nginx
/var/cache/nginx

基於容器生成鏡像無法重復、構建缺乏透明性和體積偏大的問題,因此不推薦使用這種方式構建鏡像。

2、Dockerfile 構建鏡像

Dockerfile是由一系列指令和參數構成的腳本每一條指令構建一層,因此每一條指令的內容就是描述該層應當如何構建,一個Dockerfile包含了構建鏡像的完整指令。

Dockerfile就是一個腳本來構建和定制鏡像,把每一層的修改、安裝、構建、操作都寫入腳本。以此來解決體積、鏡像構建透明等問題。

Dockerfile是一個文本文件,包含一條條指令(Instruction),每一條指令構建一層,每一條指令的內容,就是描述該層應當如何構建。

3、docker build命令

基於 dockerfile 構建鏡像使用 docker build 命令。命令是通過 Dockerfile文件構建上下文(Build Context) 來構建鏡像的。
注意:

  1. 不要把多余的文件放到構建上下文中————一般就要創建一個空目錄作為構建上下文
  2. 一般將 Dockerfile直接命名為 Dockerfile,並放在上下文根目錄,否則構建找不到(可以用-f指定)
  3. Dockerfile的每個指令都被獨立執行並創建一個新鏡像。
# 語法
[root@localhost docker]# docker build --help
Usage:  docker build [OPTIONS選項] PATH路徑 | URL | -
Build an image from a Dockerfile
Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)                    # 添加映射
      --build-arg list          Set build-time variables                                     # 設置鏡像創建時的變量
      --cache-from strings      Images to consider as cache sources
      --cgroup-parent string    Optional parent cgroup for the container
      --compress                Compress the build context using gzip                        # 壓縮構建的內容
      --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period         # 限制 CPU CFS周期
      --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota          # 限制 CPU CFS配額
  -c, --cpu-shares int          CPU shares (relative weight)                                 # 設置cpu使用權重
      --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)                  # 指定使用的CPU id
      --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)                  # 指定使用的內存 id
      --disable-content-trust   Skip image verification (default true)                       # 忽略校驗,默認開啟
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')        # 設置Dockerfile名字
      --force-rm                Always remove intermediate containers                        # 總是刪除中間容器
      --iidfile string          Write the image ID to the file                               
      --isolation string        Container isolation technology                               # 使用容器隔離技術
      --label list              Set metadata for an image                                    # 設置鏡像使用的元數據
  -m, --memory bytes            Memory limit                                                 # 內存限制
      --memory-swap bytes       Swap limit equal to memory plus swap: '-1' to enable unlimited swap     # 設置Swap的最大值為內存+swap,"-1"表示不限swap
      --network string          Set the networking mode for the RUN instructions during build (default "default")    # 在構建期間設置RUN指令網絡模式
      --no-cache                Do not use cache when building the image                     # 構建鏡像不使用緩存
      --pull                    Always attempt to pull a newer version of the image          # 總是嘗試拉取新版本鏡像
  -q, --quiet                   Suppress the build output and print image ID on success      # 安靜模式,成功后只打印鏡像ID
      --rm                      Remove intermediate containers after a successful build (default true)      # 構建成功后刪除中間容器
      --security-opt strings    Security options                                             # 安全選項
      --shm-size bytes          Size of /dev/shm                                             # /dev/shm大小
  -t, --tag list                Name and optionally a tag in the 'name:tag' format           # 鏡像的名字及標簽
      --target string           Set the target build stage to build.                         # 目標構建階段設為build
      --ulimit ulimit           Ulimit options (default [])                                  # ?

# 最簡案例
docker build .

4、Dockerfile格式

指令:

  1. 指令不區分大小寫,建議大寫。
  2. 指令可以指定若干參數。
  3. Docker按順序執行指令。
  4. Dockerfile文件必須以 FROM 指令開頭。

注釋:

  1. # 號開頭的行都將被視為注釋。解析器指令除外。
  2. 行中其他位置的 # 視為參數的一部分(不視為注釋)。

解析器指令:

  1. 不添加鏡像,也不會出現在構建步驟。
  2. 語法:# 指令 = 值,e.g:escape=\
  3. 一旦注釋、空行、解析器指令被處理,不再搜尋解析器指令,全格式化為注釋。————》解析器指令必須在Dockerfile的首部。

5、.dockerignore文件

可以添加.dockerignore 文件到構建上下文中來定義要排除的文件和目錄。
用途:構建鏡像時,在將構建上下文傳給docker daemon進程時,命令行接口就修改了上下文以排除匹配的文件或目錄。有助於避免發送大型文件或敏感文件。

使用要點:

  1. 解釋為換行符分隔的模式列表(一行一行讀取)
  2. 支持特殊通配符 **,匹配任意數量的目錄。

二、Dockerfile的指令

1、FROM指令

FROM指令為后續指令設置基礎鏡像。

指令寫法:

# 不帶標簽和摘要值,默認選擇latest標簽的鏡像
FROM <鏡像>

# 帶標簽,指定倉庫中對應標簽版本的鏡像
FROM <鏡像>:<標簽>

# 帶摘要值,指定倉庫中對應的鏡像
FROM <鏡像>@<摘要值>

# AS語法指定名稱,用處:在后期可以引用此階段構建的鏡像
FROM <鏡像> AS <名稱>

2、RUN指令

RUN指令在當前鏡像頂部創建新的層,執行定義的命令並提交結果。結果產生的鏡像由Dockerfile進一步處理。
RUN 指令是用來執行命令行命令的。Run指令在定制鏡像時是最常用的指令之一。

注意:

  1. 多少個RUN就構建多少層鏡像,多個RUN會造成鏡像臃腫,盡量將要執行的命令都寫在一個RUN里面。
  2. 多條命令執行可以使用 &&,還可以用 \ 來換行
  3. 執行到最后還需要將不需要的文件和目錄刪除
  4. Union FS有最大層數限制,如AUFS之前最大不得超過42層,現在是不得超過127層。

(1)shell格式

像直接在命令行輸入命令一樣。

命令在shell環境中運行:

  • 在Linux系統中默認為 /bin/sh -c命令;
  • 在Windows系統中默認為 cmd /S/C命令。
# 語法格式
RUN <命令>

# 案例
RUN echo '<h1>Hello,Docker!</h1>' > /usr/share/nginx/html/index.html

# 可以用反斜杠將單個RUN指令換行
RUN /bin/bash -c 'source $HOME/.bashrc;\
echo $HOME'

(2)exec格式

更類似函數調用的格式。

# 語法格式
RUN ["可執行文件(程序)", "參數1", "參數2"]

# 案例
RUN ["/bin/bash", "-c", "echo hello"]

3、CMD指令

CMD 指令一般是整個 Dockerfile 的最后一行,主要作用是:為運行中的容器提供默認值。
當Dockerfile 完成所有的環境安裝和配置后,CMD指示容器啟動時要執行的命令。

注意:Dockerfile中只能有一條CMD命令,如果寫了多條則最后一條生效。

(1)exec格式

# 語法
CMD ["可執行文件(程序)", "參數1", "參數2"]

# 案例
CMD ["sh", "-c", "echo $HOME"]
CMD ["/bin/bash"]

(2)ENTRYPOINT指令默認參數

# 語法
CMD ["參數1", "參數2"...]

# 案例??
CMD ["/usr/bin/wc","--help"]

(3)shell格式

# 語法
CMD <命令> 參數1  參數2

# 案例
CMD echo "this is test" | wc -

4、LABEL指令

LABEL 指令向鏡像添加標記。即:以鍵值對的形式給鏡像添加一些元數據(metadata)。
其中包含空格,應該使用引號和反斜杠。
一個鏡像可以定義多個標記,每個LABEL指令都會產生一層鏡像,因此盡量合並在一個LABLE指令里。

# 語法
LABEL <鍵>=<值> <鍵>=<值> <鍵>=<值>...

# 案例
LABEL version="1.0"

# 換行案例
LABEL description="asdasdsad \
標記使用多行"

# 合並標記
LABEL org.opencontainers.image.authors="runoob" version="1.2" description="test"

# 案例
[root@localhost my-centos]# docker inspect --format='{{json .ContainerConfig.Labels}}' my-centos:v2-env
{"com.example.vender":"ACME","datetime":"2023/3/22","description":"聲明容器 運行時偵聽的網絡端口",
"org.label-schema.build-date":"20210915","org.label-schema.license":"GPLv2","org.label-schema.name":"CentOS Base Image",
"org.label-schema.schema-version":"1.0","org.label-schema.vendor":"CentOS",
"version":"1.13"}

5、EXPOSE指令

EXPOSE指令通知(聲明)容器在運行時監聽指定的網絡端口。
可以指定TCP或UDP端口,默認是TCP端口。

注意:EXPOSE指令不會發布端口,只能聲明端口,發布端口,要在運行容器時用 -p-P 選項發布。

# 語法
EXPOSE <端口>[<端口>....]

# 案例
EXPOSE 8080
EXPOSE 8080 8081 8082

# 用`-P`暴露端口
[root@localhost my-centos]# docker run -tid -P my-centos:v1-net-plus
[root@localhost my-centos]# docker ps -a
CONTAINER ID   IMAGE                   COMMAND                PORTS                                                NAMES                                                                                                                                      adoring_vaughan
cbc965feaff1   my-centos:v1-net-plus   "/bin/bash"       0.0.0.0:49156->8080/tcp, :::49156->8080/tcp,    pedantic_dijkstra
                            0.0.0.0:49155->8081/tcp, :::49155->8081/tcp, 
                            0.0.0.0:49154->8082/tcp, :::49154->8082/tcp   

6、ENV指令

ENV 指令以鍵值對的形式定義環境變量。該值會存在於構建鏡像階段后續指令環境中。

# 第一種寫法(只支持單個變量設置)
ENV <鍵> <值>
# 案例:
# 注意空格,第一個空格后的整個字符串都被視為值,因此無法設置多個變量
ENV GOROOT /usr/local/go


# 第二種寫法(支持單個、多個變量設置)
ENV <鍵>=<值> ....
# 單個案例
ENV GOPATH=/Users/hqs/GolangProjects
ENV GOBIN=/Users/hqs/GolangProjects/bin
# 多個案例
ENV GOROOT=/usr/local/go GOPATH=/Users/hqs/GolangProjects \
 GOBIN=/Users/hqs/GolangProjects/bin

# 運行容器檢查環境變量
[root@localhost my-centos]# docker run -ti my-centos:v2-env
[root@c308dc947b33 /]# echo $GOROOT
/usr/local/go
[root@c308dc947b33 /]# echo $GOPATH
/Users/hqs/GolangProjects
[root@c308dc947b33 /]# echo $GOBIN 
/Users/hqs/GolangProjects/bin

7、COPY指令

COPY 指令將指定源路徑的文件或目錄復制到容器文件系統指定的目的路徑中。

# 語法
COPY [--chown=<user>:<group>] <源路徑1>...  <目標路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",...  "<目標路徑>"]

# 選項--chown:改變復制到容器內文件的用戶和用戶組(默認是UID和GID都為0的用戶和組)
# 選項--from=<name|index>:將源位置改為之前構建階段產生的鏡像,可以用名字或數字索引來標識

# <源路徑>:源文件或者源目錄,這里可以是通配符表達式,其通配符規則要滿足 Go 的 filepath.Match 規則。
# <目標路徑>:容器內的指定路徑,該路徑不用事先建好,路徑不存在的話,會自動創建。

# 通配符案例:
COPY hom* /mydir/         # 添加所有hom開頭文件
COPY hom?.txt /mydir/     # ?替換任意單個字符

# 絕對路徑案例:
COPY test /root/absoluteDir/

# 相對路徑案例:
COPY test relativeDir/


示例:
# 下載centos8的源
[root@localhost my-centos]# wget http://mirrors.aliyun.com/repo/Centos-8.repo

# Dockerfile文件如下:
FROM centos:latest
LABEL "com.example.vender"="ACME" version="1.13" description="聲明容器 \
運行時偵聽的網絡端口" "datetime"="2023/3/22"

ENV GOROOT=/usr/local/go GOPATH=/Users/hqs/GolangProjects \
 GOBIN=/Users/hqs/GolangProjects/bin

RUN echo 'nameserver 8.8.8.8' > /etc/resolve.conf && rm -rf /etc/yum.repos.d/* && \
  mkdir -p /home/hqs

COPY *.repo /home/
COPY Centos-8.repo /etc/yum.repos.d/

EXPOSE 8080 8081 8082

CMD ["/bin/bash"]

# 構建鏡像
[root@localhost my-centos]# docker build -t my-centos:v1-copy .
# 創建容器
[root@localhost my-centos]# docker run -ti cc5b86cb7cb0
[root@7b6c9c6d53f3 /]# yum install -y httpd

COPY指令遵守的復制規則:

  1. 源路徑必須位於構建上下文中,不能使用指令COPY ../something/something,因為docker build命令的第1步是發送上下文目錄及其子目錄到Docker守護進程中。
  2. 如果復制的源是目錄,則復制目錄的整個內容,包括文件系統元數據。
  3. 如果復制源是任何其他類型的文件,則它會與其元數據被分別復制。在這種情形下,如果目的路徑以斜杠(/)結尾,則它將被認為是一個目錄,源內容將被寫到“<目的>/base(<源>)”路徑中。
  4. 如果直接指定多個源,或者源中使用了通配符,則目的路徑必須是目錄,並且必須以斜杠(/)結尾。
  5. 如果目的路徑不以斜杠結尾,則它將被視為常規文件,源內容將被寫入目錄路徑。
  6. 如果目的路徑不存在,則會與其路徑中所有缺少的目錄一起被創建。

8、ADD指令

ADD指令和 COPY指令類似,ADD指令的功能是將主機構建環境(上下文)目錄中的文件和目錄、或URL標記的文件拷貝到鏡像中。

ADD指令和 COPY指令區別:

  1. ADD 指令可以使用URL地址指定。
  2. ADD 指令的歸檔文件在復制過程中能被自動解壓縮。
# 語法
ADD [--chown=<user>:<group>] <源路徑1>...  <目標路徑>
ADD [--chown=<user>:<group>] ["<源路徑1>",...  "<目標路徑>"]

# 案例
# ADD指令-三種寫法
ADD Centos-8.repo /etc/yum.repos.d/
ADD http://mirrors.aliyun.com/repo/Centos-8.repo /etc/yum.repos.d/
ADD bridge-utils-1.6.tar.xz /home/hqs

# 登錄容器后可查看到bridge-utils-1.6.tar.xz已解壓
[root@ce2e0b1bf97e hqs]# tree            
.
|-- bridge-utils-1.6
|   |-- AUTHORS
|   |-- COPYING
|   |-- ChangeLog
|   |-- Makefile.in
|   |-- README
|   |-- THANKS
|   |-- TODO
|   |-- brctl
|   |   |-- Makefile.in
|   |   |-- brctl.c

注意:

  1. 源是遠程URL地址時,復制產生的文件為600權限(-rw-------),即只有所有者有讀寫權限,其他用戶無法訪問。
  2. 源是遠程URL地址且不以反斜杠結尾,則下載文件並復制到目的路徑。
  3. 源是遠程URL地址且以反斜杠結尾,解析出文件名,並下載到"<源>/<文件名>"路徑中。
  4. 源是可識別的壓縮格式(gzip、bzip2等)的本地tar文件,解壓為目錄。
  5. 源是遠程URL地址,資源不會被解壓縮。

9、ENTRYPOINT指令

ENTRYPOINT 指令配置容器的默認入口點,也是配置容器運行的可執行文件。
類似於 CMD 指令,但其不會被 docker run 的命令行參數指定的指令所覆蓋,而且這些命令行參數會被當作參數送給 ENTRYPOINT 指令指定的程序。

(1)exec格式

docker run 的命令行參數將附加在exec格式ENTRYPOINT指令后,覆蓋CMD指令。

exec格式ENTRYPOINT可以與CMD搭配使用:exec格式的ENTRYPOINT指令設置默認命令和參數,使用CMD來設置更容易修改的其他默認值。

# 語法
ENTRYPOINT ["可執行文件(程序)", "參數1", "參數2"]

# exec格式ENTRYPOINT與CMD搭配使用示例:
FROM centos
RUN rm -rf /etc/yum.repos.d/*
ADD http://mirrors.aliyun.com/repo/Centos-8.repo /etc/yum.repos.d/

# 1.如果容器啟動默認是執行某個命令用cmd即可
#CMD ["/bin/bash"]

# 2.如果容器啟動默認是執行某個腳本程序則用entrypoint
#ENTRYPOINT ["/usr/local/sbin/test.py"]

# 3.如果執行的腳本可以有參數的話:
#ENTRYPOINT ["/usr/local/sbin/test.py", "-f", "/usr/local/conf/conf.json"]

# 4.如果執行的腳本參數有變換需求的話entrypoint和cmd一起用
ENTRYPOINT ["/usr/local/sbin/test.py", "-f"]
CMD ["/usr/local/conf/conf.json"]


# 1、不傳參運行
$ docker run -tid test:v3   # 容器內會默認運行命令,啟動主進程。

# 2、傳參運行
$ docker run -tid test:v3 /home/hqs/conf.json    # 容器內會默認運行命令,啟動主進程

[root@localhost my-centos]# docker ps -a --no-trunc
CONTAINER ID     IMAGE     COMMAND                                              CREATED              STATUS    PORTS     NAMES
7fa2cd3f1f4cc   test:v3   "/usr/local/sbin/test.py -f /home/hqs/conf.json"         2 seconds ago        Created             competent_proskuriakova
bd9b3b310d002   test:v3   "/usr/local/sbin/test.py -f /usr/local/conf/conf.json"   35 seconds ago       Created             suspicious_burnell

docker run 時,可以使用 --entrypoint 選項覆蓋ENTRYPOINT指令:

$ docker run -tid --entrypoint /bin/bash/ls  test:v3 -lrt
[root@localhost my-centos]# docker ps -a --no-trunc
CONTAINER ID  IMAGE     COMMAND       CREATED              STATUS                     PORTS     NAMES
5466ed9a4   test:v3   "ls -lrt"      3 seconds ago        Exited (0) 3 seconds ago            wizardly_feistel

(2)shell格式

這種方式會在/bin/sh -c中執行,會忽略任何CMD或者docker run命令行選項。

缺點:ENTRYPOINT指令將作為 /bin/sh -c 的子命令啟動,不傳任何其他信息,不會接受系統信號,也不會接受docker stop中止信號。

為了確保 docker stop 能夠停止長時間運行ENTRYPOINT的容器,推薦使用exec格式。

# 語法
ENTRYPOINT 命令 參數1  參數2

# shell格式ENTRYPOINT示例:
FROM ubuntu
ENTRYPOINT top -b
# 構建鏡像
[root@localhost my-ubuntu]# docker build -t test_shell_entry .
Sending build context to Docker daemon   2.56kB
Step 1/2 : FROM ubuntu
latest: Pulling from library/ubuntu
4d32b49e2995: Pull complete 
Digest: sha256:bea6d19168bbfd6af8d77c2cc3c572114eb5d113e6f422573c93cb605a0e2ffb
Status: Downloaded newer image for ubuntu:latest
 ---> ff0fea8310f3
Step 2/2 : ENTRYPOINT top -b
 ---> Running in 09805224b170
Removing intermediate container 09805224b170
 ---> e84ae9ca3b7e
Successfully built e84ae9ca3b7e
Successfully tagged test_shell_entry:latest
# 查看鏡像
[root@localhost my-ubuntu]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED          SIZE
test_shell_entry   latest    e84ae9ca3b7e   44 seconds ago   72.8MB
ubuntu             latest    ff0fea8310f3   12 days ago      72.8MB
# 啟動容器
[root@localhost my-ubuntu]# docker run -ti --name test test_shell_entry
top - 19:39:21 up  3:27,  0 users,  load average: 0.01, 0.06, 0.06
Tasks:   2 total,   1 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1982.6 total,    500.1 free,    646.7 used,    835.7 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   1172.9 avail Mem 
# docker stop 等了很久停止容器成功???


# 加入exec命令示例:
[root@localhost my-ubuntu]# cat Dockerfile 
FROM ubuntu
ENTRYPOINT exec top -b
[root@localhost my-ubuntu]# docker build -t top .
[root@localhost my-ubuntu]# docker run -it --name test_exec_entry top
top - 19:45:01 up  3:33,  0 users,  load average: 0.00, 0.02, 0.05
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1982.6 total,    498.3 free,    648.3 used,    836.0 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   1171.1 avail Mem 
# docker stop 迅速停止容器成功

注意:

  1. 如果 Dockerfile 中如果存在多個 ENTRYPOINT 指令,僅最后一個生效。
  2. 當指定了 ENTRYPOINT 后, CMD 的含義就發生了改變,不再是直接的運行其命令,而是將 CMD 的內容作為參數傳給 ENTRYPOINT 指令。
  3. 要確保 docker stop 能正確終止一直執行的 ENTRYPOINT,需要使用 exec 來啟動命令。

10、VOLUME指令

創建一個可以從本地主機或其他容器訪問的掛載點。

作用:

  1. 避免重要的數據,因容器重啟而丟失,這是非常致命的。(數據保存在主機)
  2. 避免容器不斷變大。(數據不在容器,不影響容器大小)
# 語法
VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>

# 案例
VOLUME ["/opt/log/"]
# 分別啟動兩個容器,實現文件共享
[root@localhost my-centos]# docker run -tid -v "$(pwd)"/target:/opt/log/  my-centos:v7-vol
[root@localhost my-centos]# docker run -tid -v "$(pwd)"/target:/app my-centos:v7-vol

# 雖然傳遞了文件到共享目錄,但是容器可寫層大小為0
[root@localhost target]# docker ps -s
CONTAINER ID   IMAGE           COMMAND       CREATED         STATUS         PORTS     NAMES                   SIZE
3292f3b32b35   my-centos:vol   "/bin/bash"   6 minutes ago   Up 6 minutes             youthful_banzai         0B (virtual 231MB)
ea772648df98   my-centos:vol   "/bin/bash"   6 minutes ago   Up 6 minutes             focused_johnson         0B (virtual 231MB)

啟動容器 docker run 的時候,我們可以通過 -v 參數修改掛載點。

11、WORKDIR指令

指定工作目錄。用 WORKDIR 指定的工作目錄,會在構建鏡像的每一層中都存在(每一層都能訪問)。

# 語法
WORKDIR <工作目錄路徑>

# 案例
WORKDIR /home/hqs
WORKDIR apache
WORKDIR conf
# 登錄后路徑為:
[root@localhost my-centos]# docker exec -ti 6425fa66b9ec /bin/bash
[root@6425fa66b9ec conf]# pwd
/home/hqs/apache/conf

# 可與搭配ENV指令使用
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
# 最終路徑則為 /path/$DIRNAME。

注意:

  1. 一個 Dockerfile 可以多次使用 WORKDIR 指令。
  2. 若提供相對路徑,該路徑將相對於前面的 WORKDIR 指令的路徑。
  3. WORKDIR 指令可以在ENV設置變量之后調用環境變量

12、其他指令(USER\ARG\SHELL)

USER:設置運行鏡像時使用的用戶名(或UID)和可選的用戶組(或GID),Dockerfile中的任何RUN、CMD和ENTRYPOINT指令也會使用這個指定的身份。

ARG:定義一個變量,用戶可以在使用--build-arg = 標志執行docker build命令構建時將其傳遞給構建器。

SHELL:用於指定shell格式以覆蓋默認的shell。

三、Dockerfile指令使用要點

1、exec和shell格式

RUNCMDENTRYPOINT指令都會用到 exec 和 shell 格式。

一般應該首選 exec 格式,這樣的指令可讀性更強,更容易理解。RUN 指令兩種格式均可。

如使用 CMD 指令為 ENTRYPOINT 指令提供默認參數,則兩個指令都應以 JSON 數組格式指定。

(1)exec格式指令直接調用命令,環境變量不會被shell解析

直接調用的案例:

# 創建上下文環境目錄和Dockerfile
[hqs-docker@hecs-hqs-01 tester01]$ cat Dockerfile 
FROM ubuntu
ENV name Tester
ENTRYPOINT ["/bin/echo", "Hello,$name"]

# 構建鏡像
[hqs-docker@hecs-hqs-01 tester01]$ docker build -t tester01 .

# 運行容器
[hqs-docker@hecs-hqs-01 tester01]$ docker run tester01
Hello,$name       《——————參數中的環境變量沒有被shell解析

加入/bin/sh -c 可以讓環境變量被shell解析

# 創建上下文環境目錄和Dockerfile
[hqs-docker@hecs-hqs-01 ~]$ cp -r tester01/ tester02/

[hqs-docker@hecs-hqs-01 tester02]$ cat Dockerfile 
FROM ubuntu
ENV name Tester02
ENTRYPOINT ["/bin/sh", "-c", "echo Hello,$name"]

# 構建鏡像
[hqs-docker@hecs-hqs-01 tester02]$ docker build -t tester02 .

# 運行容器
[hqs-docker@hecs-hqs-01 tester02]$ docker run tester02
Hello,Tester02    《——————參數中的環境變量已經被shell解析

(2)shell格式底層會默認調用/bin/sh -c執行命令

# 創建上下文環境目錄和Dockerfile
[hqs-docker@hecs-hqs-01 tester03]$ cat Dockerfile 
FROM ubuntu
ENV name Tester03
ENTRYPOINT echo "Hello,$name!"

# 構建鏡像
[hqs-docker@hecs-hqs-01 tester03]$ docker build -t tester03-shell .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM ubuntu
 ---> ff0fea8310f3
Step 2/3 : ENV name Tester03
 ---> Running in d2b492215377
Removing intermediate container d2b492215377
 ---> 21ca9abdb792
Step 3/3 : ENTRYPOINT echo "Hello,$name!"
 ---> Running in 8793060549fa
Removing intermediate container 8793060549fa
 ---> 98d0dde74246
Successfully built 98d0dde74246
Successfully tagged tester03-shell:latest

# 運行容器
[hqs-docker@hecs-hqs-01 tester03]$ docker run tester03-shell
Hello,Tester03!     《————環境變量已經被shell解析

(3)exec格式沒有運行bash和sh的開銷

可以在沒有bash和sh的鏡像中運行,如scratch

# 案例1:
FROM scratch
ADD centos-7-docker.tar.xz /
CMD ["/bin/bash"]

# exec案例:
# 構建上下文和dockerfile
[hqs-docker@hecs-hqs-01 hello01]$ cat Dockerfile 
FROM scratch
COPY hello /
CMD ["/hello"]
# 編譯出hello文件
[hqs-docker@hecs-hqs-01 hello01]$ cat hello.c 
#include<stdio.h>
void main (){
    printf("hello docker\n");
}
[hqs-docker@hecs-hqs-01 hello01]$ gcc --static hello.c -o hello
# 構建鏡像
[hqs-docker@hecs-hqs-01 hello01]$ docker build -t hello01 .
# 容器運行
[hqs-docker@hecs-hqs-01 hello01]$ docker run hello01
hello docker


# shell案例:
# 構建上下文和dockerfile
[hqs-docker@hecs-hqs-01 ~]$ cp -r hello01/ hello02/
[hqs-docker@hecs-hqs-01 hello02]$ cat Dockerfile 
FROM scratch
COPY hello /
CMD /hello
# 構建鏡像
[hqs-docker@hecs-hqs-01 hello02]$ docker build -t hello02 .
# 容器運行
[hqs-docker@hecs-hqs-01 hello02]$ docker run hello02
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknown.

2、RUN、CMD和ENTRYPOINT指令的區別和聯系

  1. 執行時間不一樣:RUN指令執行命令並創建新的鏡像層,RUN先於CMDENTRYPOINT指令在構建鏡像時執行;而CMDENTRYPOINT指令在每次啟動容器時才執行。
  2. 功能不一樣:RUN經常用於安裝應用程序和軟件包,並被固化在所生成的鏡像中。CMD指令的主要目的是為運行容器提供默認值,即默認執行的命令及其參數。
  3. CMDENTRYPOINT執行區別:ENTRYPOINT指令中的參數始終會被 docker run 命令使用,不可改變;而CMD指令中的額外參數可以在執行docker run命令啟動容器時被動態替換掉,會被docker run命令所覆蓋。
  4. CMDENTRYPOINT一起使用情況:ENTRYPOINT指令作為可執行文件,而CMD指令則為ENTRYPOINT指令提供默認參數。
  5. CMDENTRYPOINT搭配使用要求:如果CMD指令省略可執行文件,必須指定ENTRYPOINT指令;
  6. 必須使用ENTRYPOINT的情況:當容器作為可執行文件時,應該定義ENTRYPOINT指令。

3、組合使用CMD和ENTRYPOINT指令

CMDENTRYPOINT 指令都可以定義運行容器時要執行的命令。組合使用規則:

  1. Dockerfile中應該至少定義一個CMDENTRYPOINT指令。(至少要有一個)
  2. 將整個容器作為一個可執行文件時應當定義ENTRYPOINT指令。(必須定義ENTRYPOINT的情況)
  3. CMD指令應為ENTRYPOINT指令提供默認參數,或者用於容器中執行臨時命令。(兩個都有的情況)
  4. 當使用替代參數運行容器時,CMD指令的定義將會被覆蓋。(docker run時指定參數的情況)

如果CMD指令從基礎鏡像定義,那么ENTRYPOINT指令的定義會將CMD指令重置為空值。在這種情形下,必須在當前鏡像中為CMD指令指定一個實際的值。(不太好理解)

四、Dockerfile構建案例

1、centos-nginx鏡像案例

在centos鏡像的基礎上安裝nginx服務器軟件構建出新的鏡像。

(1)顯示nginx首頁原本信息

# 1.構建上下文和所需的文件
[root@localhost ~]# mkdir dockerfile-test
[root@localhost ~]# cd dockerfile-test/
[root@localhost dockerfile-test]# touch nginx.repo
[root@localhost dockerfile-test]# touch Dockerfile

# 2.編輯Dockerfile
[root@localhost dockerfile-test]# cat Dockerfile 
# 引入基礎鏡像
FROM centos
# 設置作者
LABEL maintainer='hqs'
# 清空repo文件
RUN rm -rf /etc/yum.repos.d/*
# 復制nginx.repo
COPY ./nginx.repo /etc/yum.repos.d
# 更新緩存
RUN yum makecache
# 安裝nginx
RUN yum install -y nginx
# 改NGINX首頁
# 聲明對外暴露的端口
EXPOSE 80
# 不以守護進程啟動nginx的命令
CMD ["nginx", "-g", "daemon off;"]

# 3.編輯的nginx.repo
[root@localhost dockerfile-test]# cat nginx.repo 
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

# 4.鏡像構建時網絡問題處理(非必須)
# 報錯:WARNING: IPv4 forwarding is disabled. Networking will not work.
解決辦法:
vi /etc/sysctl.conf
net.ipv4.ip_forward=1         #添加這段代碼
# 重啟network服務
systemctl restart network
# 查看是否修改成功 (備注:返回1,就是成功)
[root@studyCMachine aaaaaaa]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

# 5.構建鏡像
[root@localhost dockerfile-test]# docker build -t centos-nginx-hqs:1.0 .

# 6.啟動容器
[root@localhost dockerfile-test]# docker run --rm -d -p 8000:80 --name my-nginx centos-nginx-hqs:1.0
e5be77c444922817b69acc15810d186634765d27ec0d8ea8e7b345acffc610fa

# 7.訪問驗證
[root@localhost dockerfile-test]# curl 127.0.0.1:8000
<!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>

或

在瀏覽器上訪問http://192.168.100.111:8000/

(2)修改nginx首頁信息

# 1.復制生成新的上下文環境和相關文件
[root@localhost ~]# cp -r dockerfile-test/ dockerfile-test2/
[root@localhost ~]# cd dockerfile-test2/

# 2.修改Dockerfile文件
[root@localhost dockerfile-test2]# vi Dockerfile 
# 引入基礎鏡像
FROM centos
# 設置作者
LABEL maintainer='hqs'
# 清空repo文件
RUN rm -rf /etc/yum.repos.d/*
# 復制nginx.repo
COPY ./nginx.repo /etc/yum.repos.d
# 更新緩存
RUN yum makecache
# 安裝nginx
RUN yum install -y nginx
# 改NGINX首頁
RUN echo "Hello! Please test the nginx server " > /usr/share/nginx/html/index.html 
# 聲明對外暴露的端口
EXPOSE 80
# 不以守護進程啟動nginx的命令
CMD ["nginx", "-g", "daemon off;"]

# 3.構建鏡像
[root@localhost dockerfile-test2]# docker build -t centos-nginx-hqs:2.0 .

# 4.啟動容器
[root@localhost dockerfile-test2]# docker run -d -p 8080:80 --name my-nginx-2 centos-nginx-hqs:2.0
749444ad2183c322978c7bf4d58c3f6a1ae617b8f49737d4a79d7ba2b2e76fea

# 5.驗證
[root@localhost dockerfile-test2]# curl 127.0.0.1:8080
Hello! Please test the nginx server 
或
瀏覽器訪問:http://192.168.100.111:8080/

2、httpd服務構建

執行以下操作前,先創建上下文環境,拷貝repo文件

mkdir http1.0
cd http1.0
cp /etc/yum.repos.d/CentOS-Base.repo ./local.repo

(1)准備Dockerfile

FROM centos:centos7
LABEL maintainer='zrl'
RUN rm -rf /etc/yum.repos.d/*
COPY ./local.repo /etc/yum.repos.d
RUN yum makecache
RUN yum install -y httpd
EXPOSE 80
CMD ["-D", "FOREGROUND"]
ENTRYPOINT ["/usr/sbin/httpd"]

(2)構建鏡像和啟動容器

# 構建鏡像
[root@localhost http:v1.0]# docker build -t http:v1.0 .

# 啟動容器
[root@localhost http:v1.0]# docker run -tid --name web -p 8000:80 http:v1.0 
18121bb92601e6a85d0c53b8bfe08338e5031f75a5e3a36078ae0ca898e89280
[root@localhost http:v1.0]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                                   NAMES
18121bb92601   http:v1.0   "/usr/sbin/httpd -D …"   4 seconds ago   Up 3 seconds   0.0.0.0:8000->80/tcp, :::8000->80/tcp   web

# 訪問測試
http://10.10.10.111:8000/

3、httpd服務構建進階

centos7鏡像編寫dockerfile文件,構建http服務,上傳index.html文件到鏡像/var/www/html目錄,內容為"hello apache"
鏡像暴露80端口,且修改參數HOSTNAME為www.example.com,設置httpd服務前台啟動,容器將8080端口映射到容器內部80端口。

[root@localhost ~]# mkdir http2.0
[root@localhost yum.repos.d]# cp CentOS-Base.repo /root/http2.0/local.repo

# 編輯index.html文件
[root@localhost http2.0]# vi index.html
hello apache

# 編輯Dockerfile
[root@localhost http2.0]# vi Dockerfile
FROM centos:centos7
LABEL maintainer='zrl'
RUN rm -rf /etc/yum.repos.d/*
COPY ./local.repo /etc/yum.repos.d
RUN yum makecache
RUN yum install -y httpd
COPY ./index.html /var/www/html
EXPOSE 80
CMD ["-D", "FOREGROUND"]
ENTRYPOINT ["/usr/sbin/httpd"]

# 鏡像構建
[root@localhost http2.0]# docker build -t http:v2.0 .

# 啟動容器
[root@localhost http2.0]# docker run -tid --name http-1 -p 8080:80 -h www.example.com  http:v2.0
784ce9055d90f41b4d5329783d29780d049a31cc0729e07ac5b45a8912d1158f
[root@localhost http2.0]# docker ps 
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                   NAMES
784ce9055d90   http:v2.0   "/usr/sbin/httpd -D …"   15 seconds ago   Up 14 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp   http-1

# 查看hostname
[root@localhost http2.0]# docker inspect --format="{{.Config.Hostname}}" http-1
www.example.com

# 訪問網站
http://192.168.100.111:8080/

4、本地registry倉庫

(1)啟動registry私有倉庫容器

在本地docker宿主機上加載registry的tar包為registry:latest鏡像,並啟動為私有倉庫容器,將宿主機5000端口映射到容器的5000端口,倉庫命名為registry,設置為自啟動狀態。

# 上傳registry_latest.tar包
# 上傳完查看包的大小
[root@localhost ~]# du -sh registry_latest.tar 
26M	registry_latest.tar

# 加載鏡像
[root@localhost ~]# docker load -i registry_latest.tar 
d9ff549177a9: Loading layer  4.671MB/4.671MB
f641ef7a37ad: Loading layer  1.587MB/1.587MB
d5974ddb5a45: Loading layer  20.08MB/20.08MB
5bbc5831d696: Loading layer  3.584kB/3.584kB
73d61bf022fd: Loading layer  2.048kB/2.048kB
Loaded image: registry:latest
[root@localhost ~]# docker images
REPOSITORY            TAG              IMAGE ID       CREATED          SIZE
registry              latest           f32a97de94e1   3 years ago      25.8MB

# 啟動容器
[root@localhost ~]# docker run -d -p 5000:5000 --restart=always --name myregistry -v /opt/data/registry:/var/lib/registry registry
e6384c131de47bdb2720c7a917fb5b1aea040f16f49d9c01c1bea54dc454e184
[root@localhost ~]# docker ps 
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                       NAMES
e6384c131de4   registry    "/entrypoint.sh /etc…"   5 seconds ago    Up 4 seconds    0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   myregistry

(2)上傳鏡像到本地registry倉庫

下載官方的centos:7鏡像,將該鏡像上傳到registry倉庫。

# 下載官方的centos:7鏡像
[root@localhost ~]# docker pull centos:7
7: Pulling from library/centos
Digest: sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987
Status: Downloaded newer image for centos:7
docker.io/library/centos:7
[root@localhost ~]# docker images
REPOSITORY            TAG              IMAGE ID       CREATED          SIZE
centos                7                eeb6ee3f44bd   9 months ago     204MB

# 給已有的鏡像打標簽符合自建注冊中心格式
[root@localhost ~]# docker tag centos:7 127.0.0.1:5000/centos:7
[root@localhost ~]# docker images
REPOSITORY              TAG              IMAGE ID       CREATED          SIZE
http                    v2.0             0af11e06a37c   33 minutes ago   768MB
127.0.0.1:5000/centos   7                eeb6ee3f44bd   9 months ago     204MB
centos                  7                eeb6ee3f44bd   9 months ago     204MB

# 執行鏡像上傳
[root@localhost ~]# docker push 127.0.0.1:5000/centos:7
The push refers to repository [127.0.0.1:5000/centos]
174f56854903: Pushed 
7: digest: sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f size: 529

# 執行查看測試
[root@localhost ~]# curl http://127.0.0.1:5000/v2/_catalog
{"repositories":["centos"]}

(3)遠程上傳鏡像到本地registry倉庫

在遠程docker主機上下載registry的centos:7鏡像,將該鏡像運行為一個容器,命名為centos-7,在容器安裝net-tools工具。
將容器打包封裝為新的鏡像,命名為centos:net,重新上傳到registry。

# 1.克隆一個新的虛擬機(要先把原主機關閉,建議先創建克隆再做其他考試操作)
# 啟動兩台虛擬機

# 2.修改第二台虛擬機網卡,給一個新的IP,並重啟網絡
[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33
IPADDR=192.168.100.118
[root@localhost ~]# systemctl restart network

# 3.第二台主機清理環境(如果需要再做)
[root@localhost ~]# docker rm -f $(docker ps -qa)
[root@localhost ~]# docker rmi 127.0.0.1:5000/centos:7
[root@localhost ~]# docker rmi 192.168.100.111:5000/centos:7
[root@localhost ~]# docker rmi centos:7
[root@localhost ~]# docker images

# 4.檢查第一台虛擬機倉庫(保證是up狀態)
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
decca5395c07   registry   "/entrypoint.sh /etc…"   9 minutes ago   Up 3 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   myregistry

# 5.第二台主機配置注冊中心地址,並重啟
[root@localhost ~]# vi /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://nxwgbmaq.mirror.aliyuncs.com"],
  "insecure-registries":["192.168.100.111:5000"]
}
[root@localhost ~]# systemctl restart docker

# 6.第二台主機上拉取遠程主機倉庫中鏡像
[root@localhost ~]# docker pull 192.168.100.111:5000/centos:7
7: Pulling from centos
2d473b07cdd5: Pull complete 
Digest: sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f
Status: Downloaded newer image for 192.168.100.111:5000/centos:7
192.168.100.111:5000/centos:7
[root@localhost ~]# docker images
REPOSITORY                    TAG       IMAGE ID       CREATED        SIZE
192.168.100.111:5000/centos   7         eeb6ee3f44bd   9 months ago   204MB

# 7.第二台主機上拉起新容器
[root@localhost ~]# docker run -tid --name centos-7 192.168.100.111:5000/centos:7 /bin/bash
e22ff1d463a0bf8f8e4de027b9e046d71d34f7726197f15b85d01ec9e801ad0f

# 8.容器中安裝net-tools工具
[root@localhost ~]# docker exec -ti centos-7 /bin/bash
[root@e22ff1d463a0 /]# yum install -y  net-tools

# 9.將容器打包封裝為新的鏡像
[root@localhost ~]# docker commit centos-7 centos:net
sha256:8836665003fa0d465aa3bce1b28951ae60d2bbf6e2bed606e0ef8ac04b275ed8
[root@localhost ~]# docker images
REPOSITORY                    TAG       IMAGE ID       CREATED         SIZE
centos                        net       8836665003fa   6 seconds ago   375MB
192.168.100.111:5000/centos   7         eeb6ee3f44bd   9 months ago    204MB

# 10.重新上傳到registry
# 先打標簽
[root@localhost ~]# docker tag centos:net  192.168.100.111:5000/centos:net
[root@localhost ~]# docker images
REPOSITORY                    TAG       IMAGE ID       CREATED              SIZE
centos                        net       8836665003fa   About a minute ago   375MB
192.168.100.111:5000/cent

5、ubuntu 運行nginx鏡像

(1)創建上下文環境目錄和Dockerfile

[root@localhost ~]# mkdir ubuntu-nginx
[root@localhost ubuntu-nginx]# vi Dockerfile
FROM ubuntu
LABEL maintainer='hqs'
ADD sources.list /etc/apt/
RUN apt-get -y update
RUN apt-get install -y nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

(2)創建配置sources.list文件

在編寫sources.list文件時,需要先確認當前ubuntu系統版本:

[root@localhost ~]# docker run -ti ubuntu /bin/bash
root@cd939f604f1a:/# cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"

由此得知,當前鏡像的系統版本為 20.04

編寫sources.list文件如下:

[root@localhost ubuntu-nginx]# vi sources.list
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse

(3)構建鏡像,啟動容器

# 構建鏡像
[root@localhost ubuntu-nginx]# docker build -t my-ubuntu/nginx:v1 .
[root@localhost ubuntu-nginx]# docker images
REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
my-ubuntu/nginx   v1        9e93b415f52a   8 minutes ago   201MB

# 啟動容器
[root@localhost ubuntu-nginx]# docker run -d -p 8080:80 my-ubuntu/nginx:v1
# 訪問網頁:http://192.168.200.103:8080/  ,即可訪問網站首頁。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM