目錄
一、鏡像工作原理
二、鏡像管理
二、Dockerfile
三、構(gòu)建部署Nginx
四、構(gòu)建部署Java網(wǎng)站
鏡像:
1. 一個(gè)分層存儲(chǔ)的文件:
優(yōu)點(diǎn):易于擴(kuò)展、優(yōu)化存儲(chǔ)空間
2. 一個(gè)軟件的環(huán)境
3. 一個(gè)鏡像可以用于創(chuàng)建多個(gè)容器
4. 一種標(biāo)準(zhǔn)化的交付
一、鏡像工作原理
鏡像不是一個(gè)單一的文件,而是有多層構(gòu)成。可以通過 docker history 查看鏡像中各層內(nèi)容及大小,每層對(duì)應(yīng)著 Dockerfile中的一條指令。
$ docker history nginx:1.14
IMAGE CREATED CREATED BY SIZE COMMENT
86898218889a 3 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
3 weeks ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0B
3 weeks ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B
3 weeks ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B
3 weeks ago /bin/sh -c set -x && apt-get update && apt… 53.7MB
3 weeks ago /bin/sh -c #(nop) ENV NJS_VERSION=1.14.0.0.… 0B
3 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.14.0-… 0B
3 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
3 weeks ago /bin/sh -c #(nop) ADD file:e6ca98733431f75e9… 55.3MB
容器其實(shí)是在鏡像的最上面加了一層讀寫層,在運(yùn)行的容器中有文件改動(dòng)時(shí),會(huì)先從鏡像里把要寫的文件復(fù)制到容器自己的文件系統(tǒng)中,都會(huì)寫到這個(gè)讀寫層。如果容器刪除了,最上面的讀寫層也就刪除了,改動(dòng)也就丟失了。所以無論多少個(gè)容器共享一個(gè)鏡像,所做的寫操作都是從鏡像的文件系統(tǒng)中復(fù)制過來操作的,并不會(huì)修改鏡像的源文件,這種方式提高了磁盤利用率。
若想持久化這些改動(dòng),可以通過 docker commit 將容器保存成一個(gè)新的鏡像。
二、鏡像管理
常用選項(xiàng):
$ docker image –help
OPTIONS DESCRIBE
ls/images 列出鏡像
pull 從倉庫拉取鏡像到本地
push 從本地上傳鏡像到倉庫
inspect 顯示詳情
history 鏡像歷史信息
import 導(dǎo)入tar歸檔的容器文件系統(tǒng)創(chuàng)建鏡像
save 保存一個(gè)鏡像到tar歸檔文件
load 從tar歸檔或標(biāo)準(zhǔn)輸入導(dǎo)入鏡像
rm 移除一個(gè)或多個(gè)鏡像
build 從Dockerfile構(gòu)建鏡像
tag 創(chuàng)建一個(gè)引用源鏡像標(biāo)記目標(biāo)鏡像
Example:
從倉庫拉取鏡像
docker pull nginx:1.14
保存鏡像到tar歸檔文件
$ docker image save nginx:1.14 > myweb.tar
從tar歸檔或標(biāo)準(zhǔn)輸入導(dǎo)入鏡像
$ docker image load < myweb.tar
引用源鏡像標(biāo)記目標(biāo)鏡像
$ docker image tag nginx:1.14 web:v1
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat latest 41a54fe1f79d 2 weeks ago 463MB
nginx 1.14 86898218889a 3 weeks ago 109MB
web v1 86898218889a 3 weeks ago 109MB
centos 7 5182e96772bf 7 weeks ago 200MB
centos latest 5182e96772bf 7 weeks ago 200MB
二、Dockerfile
官方倉庫雖然有數(shù)十萬的鏡像資源,但在絕大多數(shù)情況下都不符合我們的需求,通常我們都會(huì)自己構(gòu)建鏡像。Dockfile 是一種被 Docker 程序解釋的腳本, Dockerfile 由一條一條的指令組成,每條指令對(duì)應(yīng) Linux 下面的一條命令。Docker 程序?qū)⑦@些 Dockerfile 指令翻譯真正的Linux命令。Docker 程序?qū)⒆x取 Dockerfile,根據(jù)指令生成定制的 image。
*注意:每一條指令就相當(dāng)于給鏡像加了一層,一個(gè)鏡像不能超過 127 層,請(qǐng)惜字如金!
官方文檔:https://docs.docker.com/engine/reference/builder/
常用指令:
OPTIONS DESCRIBE
FROM 基于哪個(gè)鏡像構(gòu)建新鏡像
MAINTAINER(棄用) 鏡像維護(hù)者信息
LABEL 同上,但用法更加靈活
RUN 構(gòu)建鏡像時(shí)運(yùn)行的Shell命令
COPY 拷貝文件或目錄到鏡像中
CMD 運(yùn)行容器時(shí)執(zhí)行,如果有多個(gè)CMD指令,最后一個(gè)生效
ENTRYPOINT 運(yùn)行容器時(shí)執(zhí)行,如果有多個(gè)CMD指令,最后一個(gè)生效。可單獨(dú)使用,也可與CMD配合使用
USER 為RUN、CMD、ENTRYPOINT執(zhí)行指令指定運(yùn)行用戶
EXPOSE 聲明容器運(yùn)行的服務(wù)端口
WORKDIR 為RUN、CMD、ENTRYPOINT、COPY和ADD設(shè)置工作目錄
VOLUME 指定掛載點(diǎn),使容器中的一個(gè)目錄具有持久化存儲(chǔ)數(shù)據(jù)的功能
ENV 設(shè)置環(huán)境變量
ENTRYPOINT與CMD的區(qū)別在于ENTRYPOINT可以使用CMD作為參數(shù),通常都是用作啟動(dòng)后臺(tái)服務(wù)。
先來一個(gè)簡(jiǎn)單的 Dockerfile
創(chuàng)建一個(gè)工作目錄,在工作目錄下創(chuàng)建一個(gè)py腳本
FROM 指明以 centos:latest 作為基礎(chǔ)鏡像
COPY 指明復(fù)制源文件 test.py 到容器的 /tmp 目錄下,test.py沒指明路徑,會(huì)運(yùn)行 build 命令的當(dāng)前目錄下查找。
CMD 在容器啟動(dòng)時(shí)運(yùn)行的命令
$ mkdir work
$ cd work/
$ cat test.py
#!/usr/bin/env python
print 'hello,container!'
$ cat Dockerfile
# Description: test image
FROM centos:latest
LABEL maintainer="Qukecheng "
COPY test.py /tmp
CMD python /tmp/test.py
docker build 命令是根據(jù)上下文自動(dòng)構(gòu)建鏡像。構(gòu)建上下文指定位置PATH或文件集URL,PATH是本地文件系統(tǒng)上的目錄,URL是一個(gè)Git倉庫地址。
構(gòu)建由 Docker 守護(hù)程序運(yùn)行,而不是CLI。構(gòu)建過程第一件事是將整個(gè)上下文(遞歸)發(fā)送到守護(hù)進(jìn)程。建議空目錄作為上下文,并將 Dockerfile 保存在該目錄下,目錄中僅包含構(gòu)建 Dockerfile 所需的文件,比如剛剛創(chuàng)建的 work 目錄。
$ docker build –help
$ docker build -t myimage:v1 ./
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM centos:latest
—> 5182e96772bf
Step 2/4 : LABEL maintainer="Qukecheng "
—> Running in 804c23af5fb3
Removing intermediate container 804c23af5fb3
—> 2409cc31df3f
Step 3/4 : COPY test.py /tmp
—> 02f2546571b9
Step 4/4 : CMD python /tmp/test.py
—> Running in f3ce25242fca
Removing intermediate container f3ce25242fca
—> 72ff3d4714ca
Successfully built 72ff3d4714ca
Successfully tagged myimage:v1
使用剛剛生成的鏡像,啟動(dòng)一個(gè)容器
$ docker container run –rm myimage:v1
hello,container!
還需要注意的是:
1. 一次 RUN 指令形成新的一層,進(jìn)程讓shell命令都寫在一行,減少鏡像層,一個(gè)鏡像是不能超過 127 層的,在使用 RUN 指令時(shí),可以在每條 shell 命令的結(jié)尾用轉(zhuǎn)義換行 ""。
2. 一次 RUN 形成新的一層,如果沒有在同一層刪除,無論文件是否最后刪除,都會(huì)帶到下一層,所以要在每一層清理對(duì)應(yīng)的殘留數(shù)據(jù),減少鏡像大小。比如 yum 之后,清一下緩存。
三、構(gòu)建部署Nginx
$ tree web/
web/
├── base
│ └── Dockerfile_nginx
└── project
├── Dockerfile_nginx
└── nginx.conf
$ mkdir -pv web/{base,project}
$ cd web/base/
$ touch Dockerfile_nginx
Nginx
$ cat Dockerfile_nginx
FROM centos:latest
LABEL maintainer="Qukecheng "
RUN yum install -y gcc gcc-c++ make
openssl-devel pcre-devel gd-devel libxslt-devel
iproute net-tools telnet wget curl &&
yum clean all &&
rm -rf /var/cache/yum/*
RUN wget http://nginx.org/download/nginx-1.14.0.tar.gz &&
tar -zxf nginx-1.14.0.tar.gz &&
cd nginx-1.14.0 &&
./configure –prefix=/usr/local/nginx
–with-http_ssl_module
–with-http_v2_module
–with-http_realip_module
–with-http_image_filter_module
–with-http_gunzip_module
–with-http_gzip_static_module
–with-http_secure_link_module
–with-http_stub_status_module
–with-stream
–with-stream_ssl_module &&
make -j $(grep processor /proc/cpuinfo | wc -l) && make install &&
cd / && rm -rf nginx-1.14.0*
ENV PATH $PATH:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
開始構(gòu)建鏡像
$ docker build -t nginx1.14 -f Dockerfile_nginx ./
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx1.14 latest 2b3cd8303924 10 minutes ago 323MB
centos latest 5182e96772bf 7 weeks ago 200MB
有了基礎(chǔ)鏡像,就可以基于這個(gè)鏡像封裝項(xiàng)目到鏡像了
項(xiàng)目鏡像
$ cd project/
$ touch Dockerfile_nginx nginx.conf
$ cat Dockerfile_nginx
FROM nginx1.14
COPY nginx.conf /usr/local/nginx/conf/
$ cat nginx.conf
user nobody;
worker_processes 1;
error_log logs/error.log info;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr – $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
charset utf-8;
access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
}
}
$ docker build -t nginx:v1 -f Dockerfile_nginx ./
部署網(wǎng)站
$ docker network create web
$ docker volume create wwwroot
$ docker container run -d –name web_nginx -p 88:80 –network lnmp -v wwwroot:/usr/local/nginx/html nginx:v1
四、構(gòu)建部署Java網(wǎng)站
Java 程序依賴于 JDK 環(huán)境,我們可以把 JDK 放在宿主機(jī)上,容器以掛載形式使用,減少鏡像大小及提高性能。
$ tar -zxf jdk-8u91-linux-x64.tar.gz
$ sudo mv jdk1.8.0_91/ /usr/local/jdk1.8
$ tree java/
java/
├── apache-tomcat-8.5.16.tar.gz
└── Dockerfile
0 directories, 2 files
$ cd java/
$ cat Dockerfile
FROM centos:latest
LABEL maintainer="Qukecheng "
ENV VERSION=8.5.16
ENV JAVA_HOME=/usr/local/jdk
RUN yum install wget curl unzip iproute net-tools -y &&
yum clean all &&
rm -rf /var/cache/yum/*
COPY . /
RUN tar zxf apache-tomcat-${VERSION}.tar.gz &&
mv apache-tomcat-${VERSION} /usr/local/tomcat &&
rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* &&
mkdir /usr/local/tomcat/webapps/ROOT &&
echo '
Hello,Tomcat!
' > /usr/local/tomcat/webapps/ROOT/status.html &&
sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /usr/local/tomcat/bin/catalina.sh &&
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV PATH $PATH:/usr/local/tomcat/bin
WORKDIR /usr/local/tomcat
EXPOSE 8080
CMD ["catalina.sh", "run"]
$ docker build -t tomcat8:latest ./
$ docker container run -d –name tomcat_srv -p 89:8080 -v /usr/local/jdk1.8/:/usr/local/jdk tomcat8:latest