镜像分层结构、dockerfile详解、nginx镜像构建与优化实战"/>
docker(二)—镜像分层结构、dockerfile详解、nginx镜像构建与优化实战
1、镜像的分层结构
[root@server1 ~]# docker pull busybox 拉取测试镜像
Using default tag: latest
latest: Pulling from library/busybox
009932687766: Pull complete
Digest: sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
[root@server1 ~]# docker run -it --name test busybox 创建并运行容器,-i表示交互式 t表示打开tty终端
/ # ls
bin dev etc home proc root sys tmp usr var
/ # touch file1 创建文件
/ # touch file2 创建文件
/ # touch file3 创建文件
/ # touch file4 创建文件
/ # touch file5 创建文件
/ # ls
bin etc file2 file4 home root tmp var
dev file1 file3 file5 proc sys usr
按ctrl+d 退出
按ctrl+pq退出终端并打入后台
[root@server1 ~]# docker stop demo 停止运行容器
demo
[root@server1 ~]# docker rm demo 删除容器
demo
[root@server1 ~]# docker start test 启动容器
test
[root@server1 ~]# docker ps 显示运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a8a0978f584c busybox "sh" 7 minutes ago Up 1 second test
[root@server1 ~]# docker ps -a 显示所有的容器,包括没有运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a8a0978f584c busybox "sh" 9 minutes ago Up About a minute test
[root@server1 ~]# docker container 按tab键 ,如下就是docker相关命令
attach create export logs port restart start top wait
commit diff inspect ls prune rm stats unpause
cp exec kill pause rename run stop update
[root@server1 ~]# docker container attach test 如果想再次进入test容器终端,用attach附加到终端上
/ #
修改镜像后如何提交?
[root@server1 ~]# docker commit -m "v1" test test:v1 提交镜像,-m表示镜像描述, test表示容器名 test:v1表示起的镜像名字
sha256:fe9637cc5fe6e45a59b140353cb33b332947c6a1ba87104a433c95640a5b3ade
[root@server1 ~]# docker images 表示查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
test v1 fe9637cc5fe6 7 minutes ago 1.24MB 修改镜像后,新建了一个容器test
busybox latest ec3f0931a6e6 7 days ago 1.24MB
yakexi007/game2048 latest 19299002fdbe 5 years ago 55.5MB
[root@server1 ~]# docker history test:v1 查看镜像之前打包的历史记录
IMAGE CREATED CREATED BY SIZE COMMENT
fe9637cc5fe6 8 minutes ago sh 66B v1 是在原有的基础上加了一层
ec3f0931a6e6 7 days ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 7 days ago /bin/sh -c #(nop) ADD file:1c8507e3e9b22b977… 1.24MB
[root@server1 ~]# docker history busybox:latest 可以发现test:v1 和busybox:latest 下面2层是一样的,他们是共享的,在操作系统上他们只保存一份
IMAGE CREATED CREATED BY SIZE COMMENT
ec3f0931a6e6 7 days ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 7 days ago /bin/sh -c #(nop) ADD file:1c8507e3e9b22b977… 1.24MB 测试:
[root@server1 ~]# docker run -it --name demo test:v1
/ # ls
bin etc file2 file4 home root tmp var
dev file1 file3 file5 proc sys usr
/ # touch file6 创建文件
/ # touch file7 创建文件
/ # touch file8 创建文件
/ # touch file9 创建文件
/ # touch file10 创建文件
[root@server1 ~]# docker commit -m "v2" demo test:v2 提交
sha256:28f94093987d0814b3038cf96fde26cd53b68a78335866f5f5e274085293e493
[root@server1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa9d2757a17a test:v1 "sh" 10 hours ago Up 10 hours demo
a8a0978f584c busybox "sh" 11 hours ago Up 11 hours test
[root@server1 ~]# docker history test:v2 可以看出test:v2时在test:v1的基础上又加了一层,其它层都是一样的
IMAGE CREATED CREATED BY SIZE COMMENT
28f94093987d 2 minutes ago sh 127B v2
fe9637cc5fe6 11 hours ago sh 66B v1
ec3f0931a6e6 7 days ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 7 days ago /bin/sh -c #(nop) ADD file:1c8507e3e9b22b977… 1.24MB
[root@server1 ~]# docker history test:v1
IMAGE CREATED CREATED BY SIZE COMMENT
fe9637cc5fe6 11 hours ago sh 66B v1
ec3f0931a6e6 7 days ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 7 days ago /bin/sh -c #(nop) ADD file:1c8507e3e9b22b977… 1.24MB
但是这种方式一般不推荐,我们可以看见用户新建的层,但是不知道用户干了什么
另一种方法:编写dockerfile
[root@server1 ~]# docker rmi test:v1 删除镜像test:v1
[root@server1 ~]# docker rmi test:v2 删除镜像test:v2
[root@server1 ~]# mkdir docker
[root@server1 ~]# cd docker/
[root@server1 docker]# vim dockerfile 创建dockerfile
FROM busybox 编写干什么事情
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
[root@server1 docker]# docker build -t test:v1 . -t表示指定镜像名字 ,.表示从当前目录读取dockerfile
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM busybox 通过busybox镜像运行了一个容器,在容器内运行指令---> ec3f0931a6e6
Step 2/4 : RUN touch file1 在容器内运行指令---> Running in c39696a8e5e5
Removing intermediate container c39696a8e5e5---> 8cedd1c2f4ed
Step 3/4 : RUN mkdir dir1 在容器内运行指令---> Running in 9c1304059edc
Removing intermediate container 9c1304059edc---> 8319e6726bbb
Step 4/4 : RUN mv file1 dir1---> Running in a5afe9a0730c
Removing intermediate container a5afe9a0730c---> d83c83bcd8b2
Successfully built d83c83bcd8b2 运行完保存
Successfully tagged test:v1
[root@server1 docker]# docker history test:v1
相当于每层都执行了一个commint
2、dockerfile详解
2.1 copy
[root@server1 ~]# cd docker/
[root@server1 docker]# vim index.html
www.westos.org
[root@server1 docker]# vim dockerfile 编辑dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html / 将当前目录里的index.html 文件拷贝到/目录里
[root@server1 docker]# docker build -t test:v2 . 构建
[root@server1 docker]# docker history test:v2 查看镜像层
[root@server1 docker]# docker run --rm test:v2 ls / 也可以这样查看, --rm表示运行结果输出后就把这个删除了
bin
dev
dir1
etc
home
index.html 已经拷贝到/里了
proc
root
sys
tmp
usr
var
2.2 Add
[root@foundation50 lamp]# scp nginx-1.18.0.tar.gz server1:/root/docker 拷贝一个nginx包到server1的docker里
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz / 和copy功能相识,但是add可以归档压缩文件,还可以自动解压
[root@server1 docker]# docker build -t test:v3 . 构建
[root@server1 docker]# docker run --rm test:v3 ls / 运行
2.3 ENV(设置环境变量)
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1 设置环境变量,主机名
2.4 EXPOSE (应用端口)
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80 如果容器中应用服务,把端口暴露出来
2.5 VOLUME
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"] 有此参数表示应用容器需要持久化 ,/data 表示容器内数据卷路经,自动挂载
2.6 WORKDIR
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /dir1 指定容器内切换目录, 相当于cd命令
[root@server1 docker]# docker build -t test:v4 . 构建
[root@server1 docker]# docker run -it test:v4 运行
/dir1 # 当前路经就是WORKDIR指定的路经
/dir1 # [root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
050cb83ed10b test:v4 "sh" 17 minutes ago Up 17 minutes 80/tcp gifted_stonebraker
[root@server1 docker]# docker inspect 050cb83ed10b 表示查看此容器的具体信息 ,inspect后面跟id或者容器名,此指令可以跟容器也可以跟镜像
[root@server1 docker]# cd /var/lib/docker/volumes/0620be82b2d0a248252077c3e288754bbe2d4de69fee5975cb31099f54f513eb/_data 此宿主机的路经就被挂载到容器/data目录里
[root@server1 ~]# docker run -it test:v4 运行
/dir1 # cd /data/
/data # touch file1 创建文件
[root@server1 ~]# cd /var/lib/docker/volumes/0620be82b2d0a248252077c3e288754bbe2d4de69fee5975cb31099f54f513eb/_data
[root@server1 _data]# ls
file1
2.7 CMD和ENTRYPOINT
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /dir1
CMD echo $HOSTNAME 表示容器运行后执行命令,应用变量输出主机名
[root@server1 docker]# docker build -t test:v5 . 构建
[root@server1 docker]# docker run --rm test:v5 运行
server1另一种写法exec格式
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /dir1
CMD ["/bin/echo", "$HOSTNAME"] exec格式写法
[root@server1 docker]# docker run --rm test:v6 运行,没有解析变量直接输出了
$HOSTNAME
shell 和exec的区别
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /dir1
CMD ["/bin/sh", "-c", "echo $HOSTNAME"] shell会默认调用/bin/sh -c 执行命令 exec格式不会,所以书写时需要加上
[root@server1 docker]# docker build -t test:v7 . 构建
[root@server1 docker]# docker run --rm test:v7 运行
server1
[root@server1 docker]# vim dockerfile
FROM busybox
RUN touch file1
RUN mkdir dir1
RUN mv file1 dir1
COPY index.html /
ADD nginx-1.18.0.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /dir1
ENTRYPOINT ["/bin/echo" , "hello"]
CMD ["world"]
[root@server1 docker]# docker build -t test:v8 . 构建
[root@server1 docker]# docker run --rm test:v8
hello world
[root@server1 docker]# docker run --rm test:v8 westos 后面跟指令westos cmd原始指令会被覆盖,ENTRYPOINT不会被覆盖
hello westos
3、nginx镜像构建与优化实战
实验环境:
[root@server1 docker]# docker images | grep ^test | awk '{print $1":"$2}' 列出所有镜像
test:v8
test:v6
test:v5
test:v7
test:v4
test:v3
test:v2
test:v1
[root@server1 docker]# docker rmi 'docker images | grep ^test | awk '{print $1":"$2}'' 批量删除镜像
[root@foundation50 images]# scp rhel7.tar server1: 将基础系统镜像拷贝到server1上[root@server1 ~]# docker load -i rhel7.tar 导入系统镜像rhel7.tar
[root@server1 ~]# docker run -it --name demo rhel7 bash 运行,后面必须加命令bash不然运行不起来
[root@foundation50 lamp]# scp nginx-1.18.0.tar.gz server1: [root@server1 ~]# mv nginx-1.8.1.tar.gz docker/
[root@server1 docker]# vim dvd.repo 建立软件仓库
[dvd]
name=rhel7.6
baseurl=http://172.25.254.50/rhel7.6
gpgcheck=0[root@server1 docker]# vim dockerfile 编辑dockerfile
FROM rhel7
EXPOSE 80 指定应用端口
VOLUME ["/usr/local/nginx/html"] 挂载到默认发布目录
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb 重建索引数据库
RUN yum install -y gcc pcre-devel zlib-devel make
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
CMD ["/usr/local/nginx/sbin/nginx", "-g","daemon off;"]
此处写法,可以参考官方镜像写法。可以拉取docker pull nginx,用docker inspect nginx:latest 查看镜像具体详细信息,如下图:
[root@server1 docker]# docker build -t webserver:v1 . 构建
[root@server1 docker]# docker run -d --name nginx webserver:v1 打入后台运行容器
afb6e1903d459823172d556cfae370fb6f44d1bbc480bde39c07369a0ad8e8e8
[root@server1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afb6e1903d45 webserver:v1 "/usr/local/nginx/sb…" 7 seconds ago Up 5 seconds 80/tcp nginx
[root@server1 docker]# docker inspect nginx 查看容器具体信息
[root@server1 docker]# cd /var/lib/docker/volumes/2d30234e4c68111addecc6779ce2d35a672db45d4bdcffb677feadc706385c40/_data
[root@server1 _data]# vim index.html 创建发布页面
www.westos.org
[root@server1 _data]# curl 172.17.0.2
www.westos.org
减少镜像层数和清理中间产物
FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.18.0.tar.gz /mnt
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && cd /mnt/nginx-1.18.0 && ./configure --prefix=/usr/local/nginx && make && make install && rm -fr /mnt/nginx-1.18.0 /var/cache/yum 多个run合并为一层,减少层数并且清理中间产物
CMD ["/usr/local/nginx/sbin/nginx", "-g","daemon off;"]
[root@server1 docker]# docker build -t webserver:v2 . 构建
[root@server1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v2 be71d93244f2 44 seconds ago 258MB 镜像从303降到258 ,但是还是大需要用到多阶段构建
webserver v1 6848a8936b2d 5 hours ago 303MB
使用多阶段构建镜像
[root@server1 docker]# vim dockerfile
FROM rhel7 as build 给镜像起一个名字
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.18.0.tar.gz /mnt
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && cd /mnt/nginx-1.18.0 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx && make && make install && rm -fr /mnt/nginx-1.18.0 /var/cache/yum 加上关闭debugFROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx 将上面镜像nginx编译后的目录拷贝到当前镜像nginx目录里
CMD ["/usr/local/nginx/sbin/nginx", "-g","daemon off;"]
[root@server1 docker]# docker build -t webserver:v3 . 构建
[root@server1 docker]# docker images 查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v3 7ade9c13418e 8 seconds ago 141MB 镜像变成141M
<none> <none> b25e45edab67 9 seconds ago 255MB
webserver v2 be71d93244f2 38 minutes ago 258MB
webserver v1 6848a8936b2d 5 hours ago 303MB
[root@server1 docker]# docker run -d --name nginx webserver:v3 运行
98981f7aec375d6a005ba4785dca7f2dfa4270da7886e4485e1c7e454644099f
[root@server1 docker]# docker ps 查看运行的镜像,可以运行
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
98981f7aec37 webserver:v3 "/usr/local/nginx/sb…" 28 seconds ago Up 26 seconds nginx
[root@server1 ~]# docker rm -f nginx
nginx
[root@server1 ~]# docker run -it --rm webserver:v3 bash 运行
bash-4.2# ldd /usr/local/nginx/sbin/nginx ldd可以列出一个程序所需要得动态链接库, 可以发现nginx在运行时不仅需要nginx二进制目录,还需要调用nginx库文件,而且根据nginx编译的不同调用的库文件也不同,如果需要迁移,nginx文件和库要同时迁移linux-vdso.so.1 => (0x00007ffdf5dc7000)libdl.so.2 => /lib64/libdl.so.2 (0x00007ff1587ee000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ff1585d2000)libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007ff15839b000)libpcre.so.1 => /lib64/libpcre.so.1 (0x00007ff15813a000)libz.so.1 => /lib64/libz.so.1 (0x00007ff157f24000)libc.so.6 => /lib64/libc.so.6 (0x00007ff157b63000)/lib64/ld-linux-x86-64.so.2 (0x00007ff1589f2000)libfreebl3.so => /lib64/libfreebl3.so (0x00007ff1578e4000)
选者最精简的基础镜像
访问
[root@foundation50 images]# scp base-debian10.tar server1: 将下载好的基础镜像base-debian10.tar包拷贝到server1上
[root@server1 ~]# docker load -i base-debian10.tar 导入基础base镜像
de1602ca36c9: Loading layer 3.041MB/3.041MB
1d3b68b6972f: Loading layer 17.77MB/17.77MB
Loaded image: gcr.io/distroless/base-debian10:latest
访问
[root@server1 ~]# cd docker/
[root@server1 docker]# vim dockerfile2 编辑dockerfile2
FROM nginx:1.18.0 as base 备注:拉取nginx官方镜像时版本不要超过1.19#
ARG TIME_ZONERUN mkdir -p /opt/var/cache/nginx && \cp -a --parents /usr/lib/nginx /opt && \cp -a --parents /usr/share/nginx /opt && \cp -a --parents /var/log/nginx /opt && \cp -aL --parents /var/run /opt && \cp -a --parents /etc/nginx /opt && \cp -a --parents /etc/passwd /opt && \cp -a --parents /etc/group /opt && \cp -a --parents /usr/sbin/nginx /opt && \cp -a --parents /usr/sbin/nginx-debug /opt && \cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtimeFROM gcr.io/distroless/base-debian10COPY --from=base /opt /EXPOSE 80 443ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t webserver:v4 -f dockerfile2 . 构建 -f表示指定
[root@server1 docker]# docker images webserver 查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v4 b79c18009090 About a minute ago 31.7MB 只有31.7M
webserver v3 7ade9c13418e 6 hours ago 141MB
webserver v2 be71d93244f2 7 hours ago 258MB
webserver v1 6848a8936b2d 11 hours ago 303MB
[root@server1 docker]# docker run -d --name nginx webserver:v4 运行
7e0c515b338adddddbce69f6473dddd46189d0574eb3241eb00eacecc4f7f594
[root@server1 docker]# docker ps 查看nginx是否运行,运行成功
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8ae0a08d9ccb webserver:v4 "nginx -g 'daemon of…" 9 seconds ago Up 7 seconds 80/tcp, 443/tcp nginx
[root@server1 docker]# curl 172.17.0.2 nginx可以访问
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}
拉取镜像太慢,如何加速??
可以使用阿里云加速器
点击控制台
点击容器镜像服务
点击镜像加速器
[root@server1 docker]# cd /etc/docker/
[root@server1 docker]# vim daemon.json 生成daemon.json文件
{"registry-mirrors": [""] 拷贝自己专属的加速地址
}
[root@server1 docker]# systemctl daemon-reload
[root@server1 docker]# systemctl restart docker 重启docker服务
[root@server1 docker]# docker info 查看
[root@server1 docker]# docker pull yakexi007/mario 再次拉取速度就很快
[root@server1 docker]# docker run -d --name demo -p 80:8080 yakexi007/mario 后台运行,-p 宿主机映射到容器的8080
[root@server1 docker]# docker ps demo容器已经运行
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
507d03f5682d yakexi007/mario "python3 -m http.ser…" 7 seconds ago Up 5 seconds 0.0.0.0:80->8080/tcp demo
[root@server1 docker]# docker port demo 端口映射也已经建立
8080/tcp -> 0.0.0.0:80
访问 http://172.25.50.1/
总结:
更多推荐
docker(二)—镜像分层结构、dockerfile详解、nginx镜像构建与优化实战
发布评论