文章目录
前言
今天开始进入docker的学习
一、docker容器俗解
Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。docker就是类似的理念。现在都流行云计算了,云计算就好比大货轮。docker就是集装箱。
1.不同的应用程序可能会有不同的应用环境,比如.net开发的网站和php开发的网站依赖的软件就不一样,如果把他们依赖的软件都安装在一个服务器上就要调试很久,而且很麻烦,还会造成一些冲突。比如IIS和Apache访问端口冲突。这个时候你就要隔离.net开发的网站和php开发的网站。常规来讲,我们可以在服务器上创建不同的虚拟机在不同的虚拟机上放置不同的应用,但是虚拟机开销比较高。docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小,小就意味着省钱了。
2.你开发软件的时候用的是Ubuntu,但是运维管理的都是centos,运维在把你的软件从开发环境转移到生产环境的时候就会遇到一些Ubuntu转centos的问题,比如:有个特殊版本的数据库,只有Ubuntu支持,centos不支持,在转移的过程当中运维就得想办法解决这样的问题。这时候要是有docker你就可以把开发环境直接封装转移给运维,运维直接部署你给他的docker就可以了。而且部署速度快。
3.在服务器负载方面,如果你单独开一个虚拟机,那么虚拟机会占用空闲内存的,docker部署的话,这些内存就会利用起来。总之docker就是集装箱原理。
二、docker镜像的特点
容器的特点:
- 共享宿主机的kernel
- base镜像提供的是最小的Linux发行版
- 同一docker主机支持运行多种Linux发行版
- 采用分层结构的最大好处是:共享资源
- Copy-on-Write 可写容器层
- 容器层以下所有镜像层都是只读的
- docker从上往下依次查找文件
- 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
- 一个镜像最多127层
三、小试牛刀-部署镜像
虚拟机上操作,server1上安装docker服务
3.1 换yum源并写docker.repo文件
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
vim /etc/yum.repos.d/CentOS-Base.repo
:%s/$releasever/7/g
[root@server1 yum.repos.d]# cat docker-ce.repo
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
gpgcheck=0
3.2 安装,配置,启用docker
安装启动
yum install -y docker-ce
systemctl enable --now docker.service
解决warning问题
docker info ## 查看docker信息
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
sysctl -a|grep bridge-nf-call-iptables
cd /etc/sysctl.d
vim docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
sysctl --system
3.3 使用docker部署第一个游戏服务
docker search yakexi007
docker pull yakexi007/mario
docker history yakexi007/mario:latest #查看端口,好做端口映射
docker run -d --name game1 -p 80:8080 yakexi007/mario #启动服务并做端口映射
测试:
3.4 Dockerfile的基本使用(重要)
3.4.1 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
EXPOSE 如果容器中运行应用服务,可以把服务端口暴露出去: EXPOSE 80
VOLUME 申明数据卷,通常指定的是应用的数据挂在点: VOLUME ["/var/www/html"]
WORKDIR 为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工 作目录,如果目录不存在会自动创建。
RUN 在容器中运行命令并创建新的镜像层,常用于安装软件包: RUN yum install -y vim
CMD 与 ENTRYPOINT 这两个指令都是用于设置容器启动后执行的命令,但CMD会被 docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会 被执行。 docker
run后面的参数可以传递给ENTRYPOINT指令当作参数。
Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后 一个有效。
3.4.2 Shell和exec格式的区别
# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT echo "hello, $name"
Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面
的exec格式不会:
# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo", "hello, $name"]
3.4.3 测试实验
创建一个Dockerfile
[root@server1 docker]# cat Dockerfile
FROM demo:v1
RUN touch file2
RUN mkdir redhat
构建镜像
docker build -t demo:v2 .
查看镜像的分层结构
docker history demo:v2
运行容器
docker run -it --name demo demo:v2
测试ADD命令与ENTRYPOINT命令等
tar zcf test.tar.gz .
[root@server1 docker]# cat Dockerfile
FROM demo:v1
RUN touch file1
COPY index.html /
ADD test.tar.gz /mnt
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
ENTRYPOINT ["echo", "hello"]
CMD ["world"]
3.5 镜像的优化封装–nginx (配置阿里云镜像加速器)
优化方法
- 选择最精简的基础镜像
- 减小镜像的层数
- 清理镜像构建的中间产物
- 注意优化网络请求
- 尽量去使用构建缓存
- 使用多阶段构造镜像
其中最具有价值是选择最精简的基础镜像和使用多阶段构造镜像
- 清理实验环境:
docker images | grep demo | awk '{print $1":"$2}'
docker rmi `docker images | grep demo | awk '{print $1":"$2}'` #删除前面的容器镜像
- 配置阿里云镜像加速器
参考链接:容器镜像服务
cd /etc/docker/
vim daemon.json
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"]
}
sudo systemctl daemon-reload
sudo systemctl restart docker
官方nginx大小
3.5.1 在rhel7.0封装nginx(先调试成功)
[root@server1 ~]# ls
docker nginx.tar rhel7.tar
docker load -i rhel7.tar
docker run -it --name demo rhel7 bash
安装gcc报错:
Rpmdb checksum is invalid: dCDPT(pkg checksums): glibc-devel.x86_64 0:2.17-260.el7 - u
解决:
rpmdb --help
rpmdb --rebuilddb
继续测试在rhel7.0上安装nginx:
yum install -y gcc pcre-devel
server1传一个nginx包到demo上
docker cp nginx-1.18.0.tar.gz demo:/
yum install tar -y
tar zxf nginx-1.18.0.tar.gz
cd nginx-1.18.0
./configure
yum install -y make
make
make install
whereis nginx
nginx: /usr/local/nginx
/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx #启动nginx
server1上测试
curl 172.17.0.2
./configure
报错:
./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=
解决:yum install -y zlib-devel
最后测试结果:
到这里调试完毕。
3.5.2 写Dockerfile文件生成镜像
[root@server1 ~]# ls
docker nginx-1.18.0.tar.gz nginx.tar rhel7.tar
[root@server1 ~]# mv nginx-1.18.0.tar.gz docker/
[root@server1 ~]# cd docker/
[root@server1 docker]# ls
Dockerfile index.html nginx-1.18.0.tar.gz
Dockerfile内容
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel &> /dev/null && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.18.0 && yum remove -y gcc make && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
测试
[root@server1 docker]# pwd
/root/docker
docker build -t webserver:v1 .
结果大小不理想,233M远大与官方镜像133M
3.5.3 优化Dockerfile结构
修改Dockerfile文件(使用多阶段构造镜像)
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel &> /dev/null && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.18.0 && yum remove -y gcc make && yum clean all
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;"]
docker build -t webserver:v2 .
结果为144M,已经不错,只要是基础镜像本身占了140M,想当于nginx只占了4M
3.5.4 寻找最精简基础镜像
这次从基础镜像入手,找一款最简基础镜像
参考网站:nginx-distroless
docker search distroless #
docker pull wl86129/distroless_base #
docker pull nginx:1.18.0
docker build -t webserver:v3 .
docker build -t webserver:v4 .
修改的Dockerfile文件
FROM nginx:1.18.0 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 /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/localtime
FROM wl86129/distroless_base #这里修改对应的基础镜像即可
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
完美优化webserver:v3、webserver:v4;大小在二三十M,比官方133M小很多。