一.导入rhel7.tar镜像
dockerfile常用指令
dockerfile常用指令 | |
---|---|
FROM | 指定base镜像,如果本地不存在会从远程仓库下载。 |
MAINTAINER | 设置镜像的作者,比如用户邮箱等。 |
COPY | 把文件从build context复制到镜像支持两种形式COPY src dest 和 COPY [“src”, “dest”]。src必须指定build context中的文件或目录 |
ADD | 用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像ADD html.tar /var/www或ADD http://ip/html.tar /var/www |
ENV | 设置环境变量,变量可以被后续的指令使用:ENV HOSTNAME sevrer1.example.com |
VOLUME | 申明数据卷,通常指定的是应用的数据挂在点:VOLUME ["/var/www/html"] |
EXPOSE | 如果容器中运行应用服务,可以把服务端口暴露出去:EXPOSE 80 |
WORKDIR | 为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。 |
RUN | 在容器中运行命令并创建新的镜像层,常用于安装软件包:RUN yum install -y vim |
CMD 与 ENTRYPOINT | 这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。docker run后面的参数可以传递给ENTRYPOINT指令当作参数。Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。 |
在tmp目录下建立docker文件夹,并建立Dockerfile文件
[root@server1 ~]# cd /tmp/
[root@server1 tmp]# mkdir docker
[root@server1 tmp]# cd docker/
[root@server1 docker]# touch Dockerfile
查看已有的镜像
[root@server1 ~]# docker images
删除已有镜像的方法
docker rmi 镜像名称:版本名称
[root@server1 ~]# docker rmi ubuntu:v1
如果在删除镜像时正在被使用是无法删除(可以强制删除),可以先删除对应的容器,再删除镜像
[root@server1 ~]# docker rmi ubuntu:v2
Error response from daemon: conflict: unable to remove repository reference "ubuntu:v2" (must force) - container bff47c284a0f is using its referenced image 3433d210d0ff
查看所有容器进程
[root@server1 docker]# docker ps -a
删除vm2容器
[root@server1 docker]# docker rm vm2
vm2
再次删除ubuntu:v2就可以了
[root@server1 ~]# docker rmi ubuntu:v2
查看导入的所有镜像
[root@server1 ~]# docker images
导入rhel7镜像
[root@server1 ~]# docker load -i rhel7.tar
[root@server1 ~]# docker images
[root@server1 ~]# docker history rhel7:latest
[root@server1 ~]# docker run -it --name vm2 rhel7 bash #bash
bash-4.2# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
bash-4.2# cd /etc/yum.repos.d/
bash-4.2# ls
rhel7.repo
bash-4.2# vi dvd.repo #rhel7镜像还没有vim的命令,所以使用vi命令
bash-4.2# yum clean all
bash-4.2# yum repolist #可以列出就说明yum源没有问题
在安装软件时可能出现以下rpm数据库问题。解决方法如下
bash-4.2# yum install -y httpd
Rpmdb checksum is invalid: dCDPT(pkg checksums): systemd-libs.x86_64 0:219-30.el7 - u
最后一行显示出问题
bash-4.2# rpmdb --rebuilddb #从已安装的包头文件,反向重建RPM数据库
bash-4.2# yum install -y httpd #重新安装httpd服务就可以
ctrl+D退出rhel7
bash-4.2# exit
[root@server1 ~]# docker rm vm2
vm2
编辑之前的Dockerfile文件
[root@server1 docker]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile
FROM rhel7 #源镜像是rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
[root@server1 docker]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.70.250/westos
gpgcheck=0
构建镜像
[root@server1 docker]# docker build -t rhel7:v1 . #.表示在当前目录下
[root@server1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7 v1 3b4803a9cfd0 4 minutes ago 193MB
可以看到多了三层,就是Dockerfile文件里执行的
[root@server1 docker]# docker history rhel7:v1
IMAGE CREATED CREATED BY SIZE COMMENT
3b4803a9cfd0 7 minutes ago /bin/sh -c #(nop) CMD ["/usr/sbin/httpd" "-… 0B
af9674ea515d 7 minutes ago /bin/sh -c rpmdb --rebuilddb && yum install … 52.7MB
74ffa6d4e593 7 minutes ago /bin/sh -c #(nop) COPY file:d3452dc04a09ad4d… 66B
0a3eb3fde7fd 4 years ago 140MB Imported from -
[root@server1 docker]# cat Dockerfile
删除之前建立的2048小游戏容器vm1
[root@server1 docker]# docker rm vm1
运行rhel7:v1,起名为apache,端口映射为80
[root@server1 docker]# docker run -d --name apache -p 80:80 rhel7:v1
4f90b37fcea62f70dfabc044f9695162a4507ce0a325740803d1dddc963a08ed
在浏览器中访问172.25.70.1可以看见apache的官方页面
添加默认访问页
[root@server1 docker]# vim index.html
welcome to China!
[root@server1 docker]# vim Dockerfile
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd
COPY index.html /var/www/html/index.html
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
构建镜像rhel7:v2
[root@server1 docker]# docker build -t rhel7:v2 .
[root@server1 docker]# docker history rhel7:v2
强制删除
[root@server1 docker]# docker rm -f apache
apache
[root@server1 docker]# docker run -d --name apache -p 80:80 rhel7:v2
ba90e380766675102bfb10a738abe7a60317ba65a8394ffb2877b578ed3ec400
浏览器重新访问就会看到设置的默认发布页
强制删除apache容器(也可以不删除,但是以后建立的容器名称不能重复)
[root@server1 docker]# docker rm -f apache
apache
指定路径
[root@server1 docker]# docker run -d --name apache -p 80:80 -v /tmp/docker/website/:/var/www/html rhel7:v2
ae77f2ed404a6df542e341ef1c1e897c1692a382167d586ac91bb17e260951e6
[root@server1 docker]# docker inspect apache
修改默认发布页的内容
[root@server1 docker]# cd website/
[root@server1 website]# ls
index.html
[root@server1 website]# vim index.html
welcome to China!
hello world!
重新访问172.25.70.1
[root@server1 website]# docker images
[root@server1 docker]# docker run -it --name vm1 rhel7 bash
二.导入busybox.tar镜像,比较Shell和exec格式
获得 busybox.tar镜像,导入
[root@server1 ~]# docker load -i busybox.tar
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile #shell格式
FROM rhel7
ENV name world
ENTRYPOINT echo "hello, $name"
[root@server1 docker]# docker build -t busybox:v1 .
[root@server1 docker]# docker run --rm busybox:v1 # --rm表示执行过后就删除
hello, world
Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面
的exec格式不会
[root@server1 docker]# vim Dockerfile
FROM rhel7
ENV name world
ENTRYPOINT ["/bin/echo","hello, $name"]
重新构建镜像尝试
[root@server1 docker]# docker build -t busybox:v2 .
[root@server1 docker]# docker run --rm busybox:v2
hello, $name
正确的exec格式如下
[root@server1 docker]# vim Dockerfile
FROM rhel7
ENV name world
ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]
[root@server1 docker]# docker build -t busybox:v3 .
[root@server1 docker]# docker run --rm busybox:v3 hello, world
Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外
参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略
任何CMD或docker run提供的参数。
[root@server1 docker]# vim Dockerfile
FROM rhel7
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
[root@server1 docker]# docker build -t busybox:v4 .
[root@server1 docker]# docker run --rm busybox:v4
hello world
[root@server1 docker]# docker run --rm busybox:v4 westos
hello westos
三.在rhel7镜像中搭建nginx,优化镜像
镜像的优化方法:
l 选择最精简的基础镜像
l 减少镜像的层数
l 清理镜像构建的中间产物
l 注意优化网络请求
l 尽量去用构建缓存
l 使用多阶段构建镜像
搭建nginx
首先要获取nginx-1.15.8.tar.gz包和nginx.tar镜像
[root@server1 docker]# vim Dockerfile # 下载编译需要的安装包,写入安装编译的过程
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
把nginx-1.15.8.tar.gz移动到/tmp/docker目录下
[root@server1 ~]# mv nginx-1.15.8.tar.gz /tmp/docker/
构建nginx镜像
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# docker build -t nginx:v1 . #构建过程中可以看见下载和编译的过程
[root@server1 docker]# docker build -t nginx:v1 .
可以看出nginx:v1有276M,这算是很大的了
[root@server1 docker]# docker images nginx
删除所有容器,清除环境
[root@server1 docker]# docker ps -a
[root@server1 docker]# docker rm vm1
vm1
[root@server1 docker]# docker rm -f apache
apache
[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v1
cd36daf667548967288b5c1f75ae3b2c98f26e4642e56d1e73db1876c3222cab
访问172.25.70.1出现nginx欢迎界面
[root@server1 docker]# docker rm -f nginx
nginx
构建第二个nginx镜像
[root@server1 docker]# vim Dockerfile #添加端口
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t nginx:v2 .
[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v2
e45c9d75c309d8f878bc6107489678e3a01cbf45d5a712c613d023a405b0f87b
比较两个镜像的层级
[root@server1 docker]# docker history nginx:v1
[root@server1 docker]# docker history nginx:v2
[root@server1 docker]# docker inspect nginx
[root@server1 docker]# cd /var/lib/docker/volumes/cb19d35ba4f2340578f6aaf1b90decd14842d9994817dcbd89275ebc9c7b4259/_data
[root@server1 _data]# ls
50x.html index.html
index.html里写的是nginx的欢迎页面
[root@server1 _data]# cat index.html
编写一个测试页test.html
[root@server1 _data]# vim test.html
www.test.org
访问172.25.70.1/test.html
删除nginx容器,但是数据还在
[root@server1 _data]# cd
[root@server1 ~]# docker rm -f nginx
nginx
[root@server1 ~]# cd -
/var/lib/docker/volumes/cb19d35ba4f2340578f6aaf1b90decd14842d9994817dcbd89275ebc9c7b4259/_data
[root@server1 _data]# ls
50x.html index.html test.html
查看之前的卷数据
[root@server1 ~]# docker volume ls
清除所有没有使用的卷数据
[root@server1 ~]# docker volume prune
再次查看已经没有卷数据了
[root@server1 ~]# docker volume ls
查看容器进程
[root@server1 ~]# docker ps
[root@server1 ~]# docker ps -a
清理没有使用的容器
[root@server1 ~]# docker container prune
1.减少镜像层数,清理镜像构建的中间产物
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile #可以用&&来减少镜像层数
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel && yum clean all&& sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx && make && make install && rm -rf /mnt/nginx-1.15.8 #清理中间产物 /mnt/nginx-1.15.8
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t nginx:v3 .
查看重构后的镜像大小,比原来小了26MB
[root@server1 docker]# docker images nginx
2.使用多阶段构建镜像
编辑Dockerfile
[root@server1 docker]# vim Dockerfile
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel && yum clean all&& sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx && make && make install && rm -rf /mnt/nginx-1.15.8
FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t nginx:v4 .
查看大小减小到141M
[root@server1 docker]# docker images nginx
[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v4
[root@server1 docker]# curl 172.17.0.2
3.选择最精简的基础镜像
可以在https://github.com/GoogleContainerTools上下载
获取distroless.tar ,加载镜像
[root@server1 ~]# cd
[root@server1 ~]# docker load -i distroless.tar
668afdbd4462: Loading layer 18.39MB/18.39MB
Loaded image: gcr.io/distroless/base:lates
编辑Dockerfile文件
[root@server1 ~]# cd -
[root@server1 docker]# vim Dockerfile
FROM nginx:1.14.2 as base
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE
RUN 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 /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.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /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/localtime
FROM gcr.io/distroless/base
COPY --from=base /opt /
EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@server1 docke]# docker build -t nginx:v5 .
查看重构后的镜像大小,只有23.5MB,所以在实际构建中尽量选择最精简的base镜像。
[root@server1 docker]# docker images nginx
删除之前的nginx容器
[root@server1 docker]# docker rm -f nginx
nginx
[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v5
27e74db0b00a748fb9f9f3fa5b881bb0be7cf2f2776d460bd1537f81d99f6f82
查看ip地址
[root@server1 docker]# docker inspect nginx
看到nginx欢迎界面的html语句说明nginx搭建没有问题
[root@server1 docker]# curl 172.17.0.2