Docker是一个基于Go语言的,开源的应用容器引擎,是一个用于开发,交付和运行应用程序的开放平台。Docker使得应用程序与基础架构分开来,进而实现快速交付。
其作用包括:可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制(沙箱就是一个限制应用程序对系统资源的访问的运行环境,通常实现在虚拟机中),更重要的是容器性能开销极低。
Docker的优点:
1.快速、一致地交付应用程序。开发人员在本地写代码,使用Docker容器与同事共享工作;使用Docker将应用程序推送到测试环境中进行测试;当出现错误时,开发人员可以在开发环境中进行修复,然后重新部署到测试环境中;测试完成后将修补程序像更新的镜像一样推送给生产环境。
2.响应式部署和扩展。Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 的可移植性和轻量级的特性,还可以使您轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。
3.同一硬件上可运行更多工作负载。Docker轻巧快速,为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案。因此Docker非常适合于高密度环境以及中小型部署。通俗来讲就是用更少的资源做更多的事情。
先简单介绍一下Docker的工作流程
1.Dockerfile是镜像的源代码。你可以简单理解为创建容器镜像(Images)的脚本,可以通过它创建容器的镜像。
2.获得容器的镜像后,我们可以通过镜像在本地Docker环境拉起(run)容器(Containers),也可以对其进行stop暂停、start开启、restart重启操作。容器也可以交付commit给镜像。
3.可对镜像进行备份backup.tar。
4.Docker registry 注册表就好像一个本地仓库,你可以推送(push,也可以理解为上传)和拉取(pull,也可以理解为下载)镜像。
目前的Docker主要分为社区版(CE)和企业版(EE),本章我们将使用CE版进行操作学习。
环境介绍:一台全新的rhel7.6虚拟机,火墙和selinux均处于关闭状态。
安装docker-ce,启动服务
yum repolist yum install -y docker-ce
systemctl enable --now docker
查看docker信息,发现两条warning
docker info
sysctl -a | grep bridge-nf-call-iptables vim /etc/sysctl.d/docker.conf
cat /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1
docker服务开启自动添加docker ip
ip addr
docker服务开启会自动写入火墙策略
iptables -L
刷新内核文件,读取添加的文件
sysctl --system
再次查看发现警告已消除
docker info
测试:将2048游戏镜像添加到docker中
docker load -i game2048.tar
查看已经添加的镜像
docker images
运行容器 –name表示名称为demo 端口为真实主机的80映射到虚拟机的80端口,-d表示打入后台
docker run -d --name demo -p 80:80 game2048
docker images
docker rm -f demo
测试:网页访问172.25.9.1,可看到游戏画面,docker安装部署完成。
注意:
ctrl+p+q 将运行的交互式容器打入后台
上传busybox镜像到docker
docker load -i busybox.tar
拉起容器busybox,-i表示交互式,-t表示打开伪终端
docker run -it --name demo busybox
查看镜像
docker images
删除demo容器重新创建
docker run -it --name demo busybox
-a查看所有进程
docker ps -a
启动已有容器
docker start demo
查看进程
docker ps
进入已存在的demo容器中
docker container attach demo
上传新的镜像,源于demo容器 demo:v1
docker commit demo demo:v1 docker images
对比查看两者层级结构
docker history demo:v1 docker history busybox:latest
删除v1容器
docker rmi demo:v1 docker images
重启读取v1中的内容
docker commit demo demo:v1 docker images
删掉demo后,不影响v1容器
docker rm demo docker run -it --name demo demo:v1
对比层级结构查看,手动添加的容器没有解释每一层的作用,game2048里会对
docker ps docker history game2048:latest
解决方法:
Dockerfile文件方式导入镜像v2,history可以查看具体内容,容器用busybox
mkdir docker cd docker/ vim Dockerfile cat Dockerfile
FROM busybox RUN echo westos > testfile RUN echo hello > testfile1
在当前目录文件Dockerfile下创建镜像
docker build -t demo:v2 .
查看导入的镜像,可以查到镜像内容
docker images docker history demo:v2
可以看到层级操作的具体操作解释。
详情如下:
vim Dockerfile
注意:此处为了方便解释每条语句的含义,所以才在文中直接加了中文注释,运行时请删掉注释。
FROM busybox #镜像来源 RUN echo westos > testfile # RUN后跟shell运行语句 RUN echo hello > testfile1 COPY index.html / #COPY拷贝当前目录的index.html到容器的根目录下 ADD nginx-1.20.1.tar.gz / #ADD 解压tar包到根目录下 ENV HOSTNAME server1 #ENV 定义变量HOSTNAME为server1 EXPOSE 80 #设定端口为80 VOLUME {"/data"} #挂载目录为/data WORKDIR /data #工作空间为 /data ENTRYPOINT ["/bin/echo", "hello"] #强制输出不被覆盖 CMD ["world"] #输出会覆盖
创建容器demo:v5
–rm表示执行后丢弃,不保存cache
docker run -it --rm demo:v5 docker run -it --rm demo:v5 westos
docker rmi docker images |grep ^demo | awk '{print $3}'
导入rhel7镜像,相当于使用rhel7的内核
docker load -i rhel7.tar
编写Dokcerfile创建镜像,
vim Dockerfile
FROM rhel7 COPY dvd.repo /etc/yum.repos.d/ ADD nginx-1.20.1.tar.gz /mnt RUN rpmdb --rebuilddb RUN yum install -y gcc pcre-devel zlib-devel make WORKDIR /mnt/nginx-1.20.1 RUN ./configure &> /dev/null RUN make &> /dev/null RUN make install &> /dev/null CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
通过Dockerfile建立镜像v1,执行命令创建镜像rhel7:v1
docker build it rhel7:v1
查看端口
拉起容器,进程名为demo,
docker run -d --name demo rhel7:v1
查demo进程/容器信息
docker inspect demo
可以看到分配给nginx的ip为172.17.0.2
测试访问可访问到nginx主页
curl 172.17.0.2
主要优化途径包括:
v2镜像:减少镜像层数,合并所有RUN指令,清理镜像构建的中间产物包括编译好的安装包和缓存/mnt/nginx-1.20.1
/var/cache/*
cat Dockerfile
FROM rhel7 EXPOSE 80 COPY dvd.repo /etc/yum.repos.d/ ADD nginx-1.20.1.tar.gz /mnt WORKDIR /mnt/nginx-1.20.1 RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.20.1 /var/cache/* CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
创建镜像v2
docker build -t rhel7:v2 .
查看镜像大小
docker images rhel7
v3:尽量去用构建缓存,使用多阶段构建镜像
cat Dockerfile
FROM rhel7 as build EXPOSE 80 COPY dvd.repo /etc/yum.repos.d/ ADD nginx-1.20.1.tar.gz /mnt WORKDIR /mnt/nginx-1.20.1 RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.20.1 /var/cache/* FROM rhel7 COPY --from=build /usr/local/nginx /usr/local/nginx CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
docker build -t rhel7:v3 .
查看压缩后的镜像v3大小
v4:选择最精简的基础镜像替换原有的rhel7
cat /new/Dockerfile
FROM nginx:latest 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 gcr.io/distroless/base-debian10 COPY --from=base /opt / EXPOSE 80 443 ENTRYPOINT ["nginx", "-g", "daemon off;"]
docker build -t rhel7:v4 .
docker images rhel7
可以看到原本的300M+的镜像被我们压缩到31.9M。
先清理之前实验的所有镜像
docker ps -a docker rm -f demo docker rmi rhel7:v4 docker rmi rhel7:v3 docker rmi rhel7:v2 docker rmi rhel7:v1 docker images
镜像改名
标记原有镜像rhel7:v4 为新镜像demo:latest
docker tag rhel7:v4 demo:latest docker images
删除rhel7:v4不影响demo的使用
docker rmi rhel7:v4 docker images rhel7 docker images demo
准备好搭建本地仓库的软件tegistry
docker pull registry docker load -i registry2.tar
docker images
查看进程和层级结构
docker ps -a docker history registry:2
启动本低仓库,-v表示本地 /opt/ 映射容器中的 /var/lib ,端口映射为5000
docker run -d --name registry -v /opt/registry:/var/lib/registry -p 5000:5000 registry
查看进程是否开启
docker ps
查看本地映射的仓库路径
ls /opt/registry/ cd /opt/registry/
查看端口5000是否打开
netstat -antlp
将容器中的game2048镜像标记到本地仓库中
docker tag game2048:latest localhost:5000/game2048:latest
推行上传
docker push localhost:5000/game2048
上传成功后本地路径中也产生了文件
ls /opt/registry/ docker ps -a
删除之后,重新加载,之前的内容依然存在
docker rm -f registry docker ps -a docker run -d --name registry -v /opt/registry:/var/lib/registry -p 5000:5000 registry curl localhost:5000/v2/_catalog
rhel8系统版本中容器为podman,使用与docker相似。
docker 常用命令
可参考:https://www.runoob.com/docker/docker-command-manual.html