Docker的鏡像制作方法詳解
Docker的鏡像制作
1.1 鏡像的基本原理
Docker 的鏡像是創(chuàng)建容器的基礎(chǔ),就是一個(gè)普通文件,是一個(gè)面向 Docker 容器的只讀模板。其實(shí)鏡像是一種輕量級(jí)、可執(zhí)行的獨(dú)立軟件包,用來(lái)打包軟件運(yùn)行環(huán)境和基于運(yùn)行環(huán)境開(kāi)發(fā)的軟件,它包含運(yùn)行某個(gè)軟件所需的所有內(nèi)容(包括代碼、運(yùn)行時(shí)、庫(kù)、環(huán)境變量和配置文件),這個(gè)打包好的運(yùn)行環(huán)境就是image鏡像文件。
例如:一個(gè)鏡像可以是一個(gè)完整的 CentOS 操作系統(tǒng)環(huán)境,稱為一個(gè) CentOS 鏡像;也可以是一個(gè)安裝了 MySQL 的應(yīng)用程序,稱之為一個(gè) MySQL 鏡像等等。鏡像是一個(gè)靜態(tài)的概念,不包含任何動(dòng)態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會(huì)被改變。
1、鏡像的底層加載原理
? Docker 的鏡像實(shí)際上由一層一層的文件系統(tǒng)組成,這種層級(jí)的文件系統(tǒng) UnionFS(聯(lián)合文件系統(tǒng))。
? UnionFS:是一種分層、輕量級(jí)并且高性能的文件系統(tǒng),它支持對(duì)文件系統(tǒng)的修改作為一次提交來(lái)一層層的疊加,同時(shí)可以將不同目錄掛載到同一個(gè)虛擬文件系統(tǒng)下(unite several directories into a single virtual filesystem)。Union 文件系統(tǒng)是 Docker 鏡像的基礎(chǔ)。鏡像可以通過(guò)分層來(lái)進(jìn)行繼承,基于基礎(chǔ)鏡像(沒(méi)有父鏡像),可以制作各種具體的應(yīng)用鏡像。
2、鏡像的結(jié)構(gòu)
? 鏡像不是一個(gè)單一的文件,而是有多層構(gòu)成。可以通過(guò) docker history 鏡像
命令查看鏡像中各層內(nèi)容及大小,每層對(duì)應(yīng)著 Dockerfile 中的一條指令。
Docker 鏡像默認(rèn)存儲(chǔ)在 /var/lib/docker
目錄中 。容器其實(shí)是在鏡像的最上面加了一層讀寫層, 在運(yùn)行容器里做的任何文件改動(dòng),都會(huì)寫到這個(gè)讀寫層。如果刪除了容器,也就刪除了其最上面的讀寫層,文件改動(dòng)也就丟失了。Docker 使用存儲(chǔ)驅(qū)動(dòng)管理鏡像每層內(nèi)容及可讀寫層的容器層。
1、分層結(jié)構(gòu)的特點(diǎn)其實(shí)我們也會(huì)考慮 Docker 為什么會(huì)才用這種分層的結(jié)果,它有什么好處呢?最大的一個(gè)好處就是共享資源。
比如:有多個(gè)鏡像都從相同的 base 鏡像構(gòu)建而來(lái),那么宿主機(jī)只需在磁盤上保存一份 base 鏡像,同時(shí)內(nèi)存中也只需加載一份 base 鏡像,就可以為所有容器服務(wù)了。而且鏡像的每一層都可以被共享。
2、分層結(jié)構(gòu)的特點(diǎn)Docker 鏡像都是只讀的,當(dāng)容器啟動(dòng)時(shí),一個(gè)新的可寫層被加載到鏡像的頂部,這一層通常被稱為容器層,容器層之下的都叫鏡像層。
3、鏡像的制作方式
- 基于容器創(chuàng)建鏡像
基于現(xiàn)有容器創(chuàng)建主要使用 docker commit
命令,就是把一個(gè)容器里面運(yùn)行的程序以及該程序的運(yùn)行環(huán)境打包起來(lái)生成新的鏡像。
它的缺點(diǎn)是:在基礎(chǔ)鏡像之上做的操作不會(huì)記錄,別人不知道做了哪些操作,因此被稱為黑盒鏡像。
docker commit [選項(xiàng)] 容器ID/名稱 生成的鏡像:[標(biāo)簽] -m:說(shuō)明信息; -a:作者信息; -p:生成過(guò)程中停止容器的運(yùn)行;
# 示例 [root@localhost ~]# docker run -d --name web1 nginx:latest //創(chuàng)建一個(gè)容器 [root@localhost ~]# docker ps -a //查看運(yùn)行狀態(tài) [root@localhost ~]# docker commit web1 nginx:v1 //生成鏡像,生成之前先在容器里寫點(diǎn)東西 [root@localhost ~]# docker images //查看生成的鏡像 [root@localhost ~]# docker run -itd -p 80:80 --name web2 nginx:v1 //用生成的鏡像創(chuàng)建容器
- 基于Dockerfile創(chuàng)建常用基礎(chǔ)服務(wù)
除了手動(dòng)生成 Docker 鏡像之外,可以使用 Dockerfile 自動(dòng)生成鏡像。Dockerfile 是由一組指令組成的文件,其中每條指令對(duì)應(yīng) Linux 中的一條命令,Docker 程序?qū)⒆x取Dockerfile 中 的指令生成指定鏡像。
1.2 Dockerfile制作鏡像
鏡像的制作實(shí)際上就是定制每一層所添加的配置、文件等信息。但是命令畢竟只是命令,每次定制都得去重復(fù)執(zhí)行這個(gè)命令,而且還不夠直觀,如果我們可以把每一層修改、安裝、構(gòu)建、操作的命令都寫入一個(gè)腳本,用這個(gè)腳本來(lái)構(gòu)建、定制鏡像。這個(gè)腳本就是我們說(shuō)的 Dockerfile
Dockerfile 是一個(gè)文本文件,其內(nèi)包含了一條條的指令 (Instruction),每一條指令構(gòu)建一層,因此每一條指令的內(nèi)容,就是描述該層應(yīng)當(dāng)如何構(gòu)建。
1、Dockerfile常用指令
Dockerfile 結(jié)構(gòu)大致分為四個(gè)部分:基礎(chǔ)鏡像信息
、維護(hù)者信息
、鏡像操作指令
和 容器啟動(dòng)時(shí)執(zhí)行指令
。Dockerfile 文件每行支持一條指令,每條指令可攜帶多個(gè)參數(shù),每運(yùn)行一條指令,都會(huì)給基礎(chǔ)鏡像添加新的一層。
指令 | 解釋 |
---|---|
FROM 鏡像 | 指定基礎(chǔ)鏡像(新鏡像所基于的鏡像),第一條指令必須為 FROM 指令,每創(chuàng)建一個(gè)鏡像就需要一條 FROM 指令。 |
MAINTAINER 名字 | 說(shuō)明新鏡像的維護(hù)人信息(可以不寫) |
RUN 命令 | 在所基于的鏡像上執(zhí)行命令,并提交到新的鏡像中 |
CMD [“命令”,“參數(shù)”] | 指令啟動(dòng)容器時(shí)默認(rèn)要運(yùn)行的命令或者腳本,如果指定多條則只能最后一條被執(zhí)行(如果在啟動(dòng)容器時(shí)指定命令,則不起作用) |
EXPOSE 端口號(hào) | 指定新鏡像加載到 Docker 時(shí)要開(kāi)啟的端口(只是定義,不更改) |
ENV 環(huán)境變量 變量值 | 設(shè)置一個(gè)環(huán)境變量的值,會(huì)被后面的 RUN 使用 |
ADD 源 目標(biāo) | 將宿主機(jī)文件拷貝到容器里面去,源文件要與 Dockerfile 文件在相同目錄中(源文件是壓縮包會(huì)自動(dòng)解壓) |
COPY 源 目標(biāo) | 將本地主機(jī)上的文件或目錄復(fù)制到容器里,源文件要與 Dockerfile 文件在相同的目錄中 |
VOLUME [“目錄”] | 在容器中創(chuàng)建一個(gè)掛載點(diǎn)(自動(dòng)創(chuàng)建匿名卷) |
USER 用戶名/UID | 指定運(yùn)行容器時(shí)的用戶 |
WORKDIR 路徑 | 為后續(xù)的 RUN、CMD、ENTRYPOINT 指定工作目錄 |
ONBUILD 命令 | 指定所生成的鏡像作為一個(gè)基礎(chǔ)鏡像時(shí)所要運(yùn)行的命令 |
HEALTHCHECK | 健康檢查,定義檢查指令 |
2、Dockerfile制作鏡像:案例
- 構(gòu)建Nginx鏡像
[root@localhost ~]# docker tag hub.atomgit.com/amd64/centos:centos7 centos:7 //下載centos鏡像,并修改標(biāo)簽 [root@localhost ~]# mkdir nginx;cd nginx [root@localhost nginx]# vim Dockerfile FROM centos:7 RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/* && \ sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/* && \ sed -i 's/#baseurl=/baseurl=/g' /etc/yum.repos.d/* && \ yum -y install gcc make pcre-devel zlib-devel tar zlib ADD nginx-1.12.0.tar.gz /usr/src/ RUN cd /usr/src/nginx-1.12.0 && \ mkdir -p /usr/local/nginx && \ ./configure --prefix=/usr/local/nginx && \ make && make install && \ ln -s /usr/local/nginx/sbin/* /usr/local/sbin/ RUN rm -rf /usr/src/nginx-1.12.0 EXPOSE 80 EXPOSE 443 CMD ["nginx","-g","daemon off;"] [root@localhost nginx]# ls //將nginx源碼包拉上來(lái) Dockerfile nginx-1.12.0.tar.gz [root@localhost nginx]# docker build -t 鏡像:tag . //構(gòu)建鏡像,要注意要在有Dockerfile文件的目錄執(zhí)行
- 構(gòu)建LNMP鏡像
[root@localhost ~]# mkdir lnmp;cd lnmp [root@localhost lnmp]# vim Dockerfile FROM centos:7 # 安裝ngix RUN rm -f /etc/yum.repos.d/* && \ curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \ yum -y install epel-release && \ yum clean all && \ yum makecache && \ yum -y install nginx RUN sed -i '/^user/s/nginx/nginx\ nginx/g' /etc/nginx/nginx.conf COPY default.conf /etc/nginx/conf.d/default.conf # 安裝mariadb和php RUN yum -y install mariadb-server mariadb-devel mariadb php-mysql php php-fpm # 修改php-fpm配置文件 RUN sed -i '/^user/s/apache/nginx/g' /etc/php-fpm.d/www.conf && \ sed -i '/^group/s/apache/nginx/g' /etc/php-fpm.d/www.conf # 聲明mariadb的用戶名和密碼 ENV MARIADB_USER=root ENV MARIADB_PASS=123456 # 支持中文 ENV LC_ALL=en_US.UTF-8 # 添加并運(yùn)行腳本 ADD db_init.sh /root/db_init.sh RUN chmod 775 /root/db_init.sh RUN /root/db_init.sh ADD run.sh /root/run.sh RUN chmod 775 /root/run.sh ADD index.php /usr/share/nginx/html/index.php # 開(kāi)放的端口 EXPOSE 80 EXPOSE 3306 EXPOSE 443 EXPOSE 9000 # 每次創(chuàng)建容器運(yùn)行此腳本 CMD ["/root/run.sh"] [root@localhost lnmp]# vim default.conf server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.php index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name; include fastcgi_params; } } [root@localhost lnmp]# vim db_init.sh //數(shù)據(jù)庫(kù)初始化腳本 #!/bin/bash #初始化數(shù)據(jù)庫(kù)命令 mysql_install_db --user=mysql sleep 3 #啟動(dòng)數(shù)據(jù)庫(kù) mysqld_safe & sleep 3 # 涉及到的變量在 Dockerfile 中都已經(jīng)聲明 mysqladmin -u "$MARIADB_USER" password "$MARIADB_PASS" # 授權(quán)命令 mysql -u"$MARIADB_USER" -p"$MARIADB_PASS" -e "use mysql; grant all privileges on *.* to '$MARIADB_USER'@'%' identified by '$MARIADB_PASS' with grant option;" mysql -u"$MARIADB_USER" -p"$MARIADB_PASS" -e "grant all privileges on *.* to '$MARIADB_USER'@'localhost' identified by '$MARIADB_PASS';" h=$(hostname) mysql -u"$MARIADB_USER" -p"$MARIADB_PASS" -e "use mysql; update user set password=password('$MARIADB_PASS') where user='$MARIADB_USER' and host='$h';" [root@localhost lnmp]# vim run.sh //服務(wù)啟動(dòng)腳本 #!/bin/bash mysqld_safe & /usr/sbin/nginx & /usr/sbin/php-fpm [root@localhost lnmp]# vim index.php <?php echo date("Y-m-d H:i:s")."<br />\n"; $link=mysql_connect("localhost","root","123456"); if(!$link) echo "FAILD!"; else echo "MySQL is OK!"; phpinfo(); ?> [root@localhost lnmp]# docker build -t centos:lnmp . [root@localhost lnmp]# docker run -d --name lnmp -P centos:lnmp
1.3 多階段構(gòu)建鏡像
在 Docker 17 版本后提供的,使用多階段構(gòu)建可以在一個(gè) Dockerfile 中使用多個(gè) FROM 語(yǔ)句。每個(gè)FROM指令都可以使用不同的基礎(chǔ)鏡像,并表示開(kāi)始一個(gè)新的構(gòu)建階段。你可以很方便的將一個(gè)階段的文件復(fù)制到另一個(gè)階段,在最終的鏡像中留下你需要的內(nèi)容。
使用多階段構(gòu)建的好處:
1.減小鏡像大?。好總€(gè)構(gòu)建階段只包含必要的依賴項(xiàng)和文件,從而減小了生成的鏡像大小。這可以減少鏡像的存儲(chǔ)空間和傳輸時(shí)間。
2.提高構(gòu)建速度:每個(gè)構(gòu)建階段可以一起執(zhí)行。而且,每個(gè)構(gòu)建階段只構(gòu)建所需的內(nèi)容,從而減少了構(gòu)建時(shí)間。
3.簡(jiǎn)化 Dockerfile:使用多個(gè)構(gòu)建階段可以將 Dockerfile 分解為更小的部分,從而使Dockerfile 更加易于管理和維護(hù)。
4.提高安全性:使用多個(gè)構(gòu)建階段可以限制敏感信息的泄露。例如,在第一個(gè)構(gòu)建階段中,可以包含敏感信息,例如私有密鑰或密碼。而在第二個(gè)構(gòu)建階段中,可以只包含必要的文件和依賴項(xiàng)
? 多階段構(gòu)建案例(未使用多階段構(gòu)建)
[root@localhost ~]# mkdir demo;cd demo [root@localhost demo]# vim demo.c # include<stdio.h> int main() { printf("%s\n","This is a demo!"); return 0; } [root@localhost demo]# vim Dockerfile FROM centos:7 ENV version=1.0 WORKDIR /demo COPY demo.c . RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \ yum -y install gcc && \ gcc -v RUN gcc demo.c -o demo && \ rm -rf demo.c && \ yum -y remove gcc && \ cp demo /usr/local/bin/ CMD ["demo"] [root@localhost demo]# docker build -t demo:v1 . [root@localhost demo]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE demo v1 d05f8303b0bc 22 seconds ago 557MB
? 多階段構(gòu)建案例(使用多階段構(gòu)建)
[root@localhost demo]# vim Dockerfile //基于上面的未使用構(gòu)建,添加這兩行 FROM centos:7 ENV version=1.0 WORKDIR /demo COPY demo.c . RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \ yum -y install gcc && \ gcc -v RUN gcc demo.c -o demo && \ rm -rf demo.c && \ yum -y remove gcc && \ cp demo /usr/local/bin/ FROM centos:7 # --from表示從其他階段拷貝內(nèi)容到本階段,0表示從第一個(gè)階段拷貝到本階段 COPY --from=0 /usr/local/bin/demo /usr/local/bin/demo CMD ["demo"] [root@localhost demo]# docker build -t demo:v1 . [root@localhost demo]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE demo v2 68bc7352dcfa 13 seconds ago 204MB //使用多階段構(gòu)建 demo v1 d05f8303b0bc 9 minutes ago 557MB //未使用多階段構(gòu)建
總結(jié)
到此這篇關(guān)于Docker的鏡像制作方法的文章就介紹到這了,更多相關(guān)Docker鏡像制作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker數(shù)據(jù)存儲(chǔ)之Volumes詳解
今天小編就為大家分享一篇關(guān)于Docker數(shù)據(jù)存儲(chǔ)之Volumes詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02Docker配置MySql環(huán)境的實(shí)現(xiàn)步驟
通過(guò)使用Docker,開(kāi)發(fā)人員可以更容易地構(gòu)建、測(cè)試和交付應(yīng)用程序,同時(shí)減少了環(huán)境配置和依賴項(xiàng)管理的復(fù)雜性,本文主要介紹了Docker配置MySql環(huán)境的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),感興趣的可以了解一下2024-02-02詳解用Docker構(gòu)建MySQL主從環(huán)境
這篇文章主要介紹了詳解用Docker構(gòu)建MySQL主從環(huán)境,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07docker(alpine+golang)?中?hosts?不生效問(wèn)題解決方法
這篇文章主要介紹了docker(alpine+golang)?中?hosts?不生效問(wèn)題解決大全,本文給大家分享了三種解決方法,每種方法給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07