# class-docker **Repository Path**: lovelifelovecode/class-docker ## Basic Information - **Project Name**: class-docker - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-03-01 - **Last Updated**: 2022-03-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 入门部分 命令可以参考官网的文档:https://docs.docker.com/engine/reference/run/ ### Docker概述 作用:vmware虚拟机的高级替代版(是带环境安装的一种解决方案,程序猿经常说的的理由:这个功能在我的机器上是好的);环境隔离。 优势:体积小;启动快(秒级别) ### 安装 ![image-20220228174730137](./imgs/image-20220228174730137.png) 安装完成测试 ``` docker version # 显示 Docker 版本信息。 docker --help # 帮助 ``` ### 镜像 类似vmware安装的iso文件 **镜像命令** ``` docker images # 列出本地主机上的镜像 docker search ubuntu # 搜索镜像 docker pull ubuntu:20.04 # 下载镜像 docker rmi -f 镜像id/镜像名:tag # 删除镜像 ``` ### 容器 镜像运行的实例 容器命令 ``` docker run -it --name xjubuntu ubuntu:20.04 /bin/bash # 创建并进入,但退出后,容器就关闭了 docker run -dit --name xjubuntu ubuntu:20.04 # 后台启动容器 docker ps # 列出所有运行的容器 docker ps -a # 列出所有的容器 docker logs 容器id # 查看日志 docker start (容器id or 容器名) # 启动容器 docker restart (容器id or 容器名) # 重启容器 docker stop (容器id or 容器名) # 停止容器 docker kill (容器id or 容器名) # 强制停止容器 docker exec -it (容器id or 容器名) bashShell # 进入容器 exit # 使用 exit 退出容器 ``` ### 仓库 集中存放镜像文件的场所 https://hub.docker.com/ ### 镜像详解 思考:为什么dockerr的镜像那么小? ![image-20220228154508584](./imgs/image-20220228154508584.png) ![image-20220228154654904](./imgs/image-20220228154654904.png) ## 中级部分 ### 网络 #### **--Link** 不推荐使用!可以使用自定义网络的方式 ``` docker run -it --rm --name xjlink1 busybox sh docker run -it --rm --name xjlink2 --link xjlink1 busybox sh ping www.baidu.com ping xjlink1 ifconfig ``` #### **自定义网络** ``` docker network ls # 查看网络 docker network create 网络名 # 创建网络 docker network inspect mynet # 查看网络 ``` ``` docker network create xjnet docker run -it --rm --name xjbusybox1 --network xjnet busybox sh docker run -it --rm --name xjbusybox2 --network xjnet busybox sh ping xjbusybox1 ping xjbusybox2 ``` ### 数据 方式一:数据卷(推荐用卷名,不推荐直接用目录映射) ``` docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名 # 挂载 docker inspect 容器id # 查看容器的信息,看看数据卷是否挂载成功 docker run -it --rm -v /home/temp/:/root/ ubuntu:20.04 bash ``` 方式二:数据卷容器(容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止) 命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。 ``` docker rm -f $(docker ps -aq) # 清除所有的容器 docker run -itd --name xjubuntu1 -v /home/temp/:/root/ ubuntu:20.04 docker run -itd --name xjubuntu2 --volumes-from xjubuntu1 ubuntu:20.04 docker run -itd --name xjubuntu3 --volumes-from xjubuntu1 ubuntu:20.04 docker exec -it xjubuntu2 ls -al /root/ docker rm -f xjubuntu2 xjubuntu3 docker run -itd --name xjubuntu4 --volumes-from xjubuntu1 ubuntu:20.04 docker rm -f xjubuntu1 docker exec -it xjubuntu4 ls -al /root/ ``` ### dockerFile dockerfifile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。 #### 如何定制镜像 现在让我们以定制一个 Web 服务器为例子,来讲解镜像是如何构建的。 ``` $ docker run --name xjwebserver -d -p 80:80 nginx ``` 修改一下欢迎页面 ``` # docker exec -it xjwebserver bash # echo 'update Nginx welcome page on xj by 2022.3.1' > /usr/share/nginx/html/index.html ``` 我们修改了容器的文件,也就是改动了容器的存储层。我们可以通过 `docker diff` 命令看到具体的改动(这里有个坑,稍后再说) ``` root@xjTEST:~# docker diff xjwebserver C /run A /run/nginx.pid C /usr C /usr/share C /usr/share/nginx C /usr/share/nginx/html C /usr/share/nginx/html/index.html C /var C /var/cache C /var/cache/nginx A /var/cache/nginx/proxy_temp A /var/cache/nginx/scgi_temp A /var/cache/nginx/uwsgi_temp A /var/cache/nginx/client_temp A /var/cache/nginx/fastcgi_temp C /etc C /etc/nginx C /etc/nginx/conf.d C /etc/nginx/conf.d/default.conf C /root A /root/.bash_history ``` 现在我们定制好了变化,我们希望能将其保存下来形成镜像。 docker commit 的语法格式为: ``` docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] ``` ``` docker commit \ --author "xiaojin" \ --message "修改了默认网页" \ xjwebserver \ xjnginx:v2 docker rm -f $(docker ps -aq) # 清除所有的容器 docker images docker run -d --name web2 -p 80:80 xjnginx:v2 ``` 我们可以在 `docker images` 中看到这个新定制的镜像. 我们还可以用 `docker history` 具体查看镜像内的历史记录,如果比较 `nginx:latest` 的历史记录,我们会发现新增了我们刚刚提交的这一层。 ``` root@xjTEST:~# docker history xjnginx:v2 IMAGE CREATED CREATED BY SIZE COMMENT e240615c8538 50 seconds ago nginx -g daemon off; 1.81kB 修改了默认网页 f652ca386ed1 8 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B 8 weeks ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B 8 weeks ago /bin/sh -c #(nop) EXPOSE 80 0B 8 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B 8 weeks ago /bin/sh -c #(nop) COPY file:09a214a3e07c919a… 4.61kB 8 weeks ago /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7… 1.04kB 8 weeks ago /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0… 1.96kB 8 weeks ago /bin/sh -c #(nop) COPY file:65504f71f5855ca0… 1.2kB 8 weeks ago /bin/sh -c set -x && addgroup --system -… 61.1MB 8 weeks ago /bin/sh -c #(nop) ENV PKG_RELEASE=1~bullseye 0B 8 weeks ago /bin/sh -c #(nop) ENV NJS_VERSION=0.7.0 0B 8 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.21.4 0B 8 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B 8 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B 8 weeks ago /bin/sh -c #(nop) ADD file:ece5ff85ca549f0b1… 80.4MB ``` 新的镜像定制好后,我们可以来运行这个镜像。 ``` docker run -d --name web2 -p 80:80 xjnginx:v2 ``` > 不建议用docker commit来打包镜像,而是用dockerFile,docker commit这种做法有两个坑: > > 1. 除了打包镜像的当事人,谁也不知道里边更改了什么。 > 2. 随着时间推移,会导致镜像非常臃肿,且没法瘦身(思考一下为什么?) ![image-20220228154117552](./imgs/image-20220228154117552.png) 镜像所使用的分层存储的概念,除当前层外,之前的每一层都是不会发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。如果使用 `docker commit` 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。 #### 制作Dockerfile文件 在一个空白目录中,建立一个文本文件,并命名为 `Dockerfile`: ``` FROM ubuntu:20.04 LABEL org.opencontainers.image.authors="xiaojin" LABEL org.opencontainers.image.version="0.6" # apt install -y vim (还换源的话,安装不了) RUN echo '' > /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal main restricted' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal universe' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-updates universe' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal multiverse' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-updates multiverse' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-security universe' >> /etc/apt/sources.list \ && echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-security multiverse' >> /etc/apt/sources.list \ && apt update \ && apt -y upgrade \ && apt install -y vim \ && apt install -y net-tools \ && rm -rf /var/lib/apt/lists/* # EXPOSE 80 CMD /bin/bash # docker build -f dockerfile地址 -t 新镜像名字:TAG . # docker build -f ./Dockerfile -t xjubuntu:0.1 ``` 如果有软件是下载安装的,标准做法 ``` FROM debian:stretch RUN set -x; buildDeps='gcc libc6-dev make wget' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDeps ``` 可以看到这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 `apt` 缓存文件。这是很重要的一步,我们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。 很多人初学 Docker 制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。 ### docker-compose 部署一个项目有两种方式: 1. 把所有的服务都安装在一个容器内,这种一般是作为一个产品去发布。 2. 一个服务,一个容器。方便服务的更新迭代。 ## 高级部分 ### Swarm & k8s [Docker Swarm](https://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzI0MDQ4MTM5NQ%3D%3D%26mid%3D2247487131%26idx%3D1%26sn%3Dab26a01288355ca29fe16a50346ec8cd%26chksm%3De91b6b87de6ce291af3ad05d9842b6ad45e62d9f9d86d7474a3f38f7ba8cc4feea9817d22060%26scene%3D21%23wechat_redirect) 是 Docker 公司的容器编排系统,使用的是标准 Docker API 接口,容器使用命令和 docker 命令是一套,简单方便。一般用于10台左右的服务器集群管理,大于10台以上的,推荐用k8s Kubernetes 作为一个容器集群管理系统,用于管理云平台中多个主机上的容器应用,[Kubernetes](https://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzI0MDQ4MTM5NQ%3D%3D%26mid%3D2247509120%26idx%3D2%26sn%3D7a1541742111f5faee1716aac58bbf28%26chksm%3De918c19cde6f488a1e67f9a83ced62449027412e90ab349027e458c9a68c15dfdadb2843db63%26scene%3D21%23wechat_redirect) 的目标是让部署容器化的应用变得简单且高效,所以 Kubernetes 提供了应用部署,规划,更新,维护的一整套完整的机制。 > **k8s安装复杂当适应更多场景**,想简单了解,或者仅有10台服务器左右的,可以学下Swarm;如果用于生产,或者超过10台服务的集群,推荐学下k8s. **手工(命令)-> 服务(dockerFile)-> 项目(docker compose)-> 容器编排(swarm/k8s)** ## 其他 docker 与 podman 的故事:一个方兴未艾,一个异军突起。 **podman**(Pod Manager)是一个由 RedHat 公司推出的容器管理工具,它的定位就是 docker 的替代品。 - podman 可以替代 docker 来做容器管理工具。由于没有守护进程,比使用 docker 的时候少占用了系统资源。 - podman 没用 docker 那个 root 用户权限的问题,所以感觉比 docker 更见安全吧。 - podman 的使用方式和 docker 完全一致,直接由 docker 转过来完全没啥问题。