--- layout : post title : "Hello, Docker~" subtitle : "真香,(⑅˃◡˂⑅)" date : 2023-05-31 18:15:10 author : "Manford Fan" catalog : false header-img : "img/post-bg-universe.jpg" tags : - Docker --- 这是一个屠龙少年终成恶龙的故事,最终还是躲不过[Docker](https://www.docker.com/),一开始使用的时候,不太熟悉,本能的抗拒,慢慢的,感觉其实还可以,除了占用资源多一些。另外一直听到有些声音在说现在还在用Docker,不如用[Kubernetes](https://kubernetes.io/zh-cn/),和之前一样,Kubernetes现在之于我,相当于之前的Docker,陌生,抵触,不愿接触。所以打算先耍一耍Docker,至于Kubernetes,等时机成熟,应该是水到渠成的事情,又或者我根本就不需要[FLAG HERE~]。 Docker是一种容器化技术,可以在服务器上快速搭建容器并在不污染宿主机的情况下运行软件,而不再需要安装配置各种环境。开源Docker社区致力于改进这类技术,并免费提供给所有用户,使之获益。 ## 一、安装Docker #### 1.1 安装过程 以Debian 11为例,执行如下操作即可安装好Docker-CE,安装结束之后可以使用`docker version`或者`docker info`来查看。 ```bash apt update apt upgrade -y apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates curl -sSL https://download.docker.com/linux/debian/gpg | gpg --dearmor > /usr/share/keyrings/docker-ce.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-ce.gpg] https://download.docker.com/linux/debian $(lsb_release -sc) stable" > /etc/apt/sources.list.d/docker.list apt update apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin ``` 下载安装速度过慢的话,可以替换成国内的源站,如果需要某个特定用户可以用Docker rootless模式运行Docker,那么可以把这个用户也加入docker组,比如我们把www-data用户加进去: ```bash # 清华源站 curl -sS https://download.docker.com/linux/debian/gpg | gpg --dearmor > /usr/share/keyrings/docker-ce.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-ce.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian $(lsb_release -sc) stable" > /etc/apt/sources.list.d/docker.list # rootless apt install docker-ce-rootless-extras usermod -aG docker www-data ``` #### 1.2 检查是否成功 最后使用`docker version`查看下是否安装成功: ``` > docker version Client: Docker Engine - Community Version: 24.0.1 API version: 1.43 Go version: go1.20.4 Git commit: 6802122 Built: Fri May 19 18:06:34 2023 OS/Arch: linux/amd64 Context: default Server: Docker Engine - Community Engine: Version: 24.0.1 API version: 1.43 (minimum version 1.12) Go version: go1.20.4 Git commit: 463850e Built: Fri May 19 18:06:34 2023 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.21 GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8 runc: Version: 1.1.7 GitCommit: v1.1.7-0-g860f061 docker-init: Version: 0.19.0 GitCommit: de40ad0 ``` ## 二、安装Docker Compose 传统模式下运维人员需要运行docker run来启动各种容器,一旦容器过多,就无法一次性记住所有的运行参数和命令,这时候我们可以使用Docker Compose来解决这个问题。 Docker Compose是一种工具,用于帮助定义和共享多容器应用程序。 通过Compose,你可以创建YAML文件来定义服务,并且只需一个命令,就可以启动或清理所有内容。使用Compose的巨大优点是,你可以在文件中定义应用程序堆栈,使其位于项目存储库的根目录下(它现在受版本控制),并方便其他人参与你的项目。 其他人只需克隆你的存储库即可开始撰写应用。事实上,你可能会看到GitHub/GitLab上的很多项目现在都是这样做的。 因为我们已经安装了docker-compose-plugin,所以Docker目前已经自带 docker compose 命令,基本上可以替代docker-compose: ```bash > docker compose version Docker Compose version v2.18.1 ``` 如果某些镜像或命令不兼容,则我们还可以单独安装Docker Compose,可以使用Docker官方发布的Github直接安装最新版本: ```bash curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-Linux-x86_64 > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose ``` ## 三、其他配置 以下配置会增加一段自定义内网IPv6地址,开启容器的IPv6功能,以及限制日志文件大小,防止Docker日志塞满硬盘,还有就是修改增加国内Docker镜像源,以加速镜像的下载速度。 ```bash cat > /etc/docker/daemon.json << EOF { "registry-mirrors": [ "https://hub-mirror.c.163.com", "https://f1361db2.m.daocloud.io", "https://docker.mirrors.ustc.edu.cn", "https://registry.docker-cn.com", "https://registry.hub.docker.com" ], "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "8" }, "ipv6": true, "fixed-cidr-v6": "fd00:dead:beef:c0::/80", "experimental":true, "ip6tables":true, "bridge": "inner", "dns": [ "114.114.114.114", "8.8.8.8" ] } EOF systemctl restart docker.service ``` 使用国内加速镜像源拉取Images的时候,采用如下格式: ```bash docker pull hub-mirror.c.163.com/ceph/ceph:v16 docker pull hub-mirror.c.163.com/library/influxdb:2.4.0 ``` ## 四、Just A Minute... 先等一下,现在我已经安装配置好了Docker环境,理论上可以开始愉快的pull&run了,可总觉得,还是需要大体了解下,Docker到底是个什么东西,和虚拟机有什么区别吗,它的网络是什么样的,不同的Container之间可以相互通信吗?无疑,Docker是一个非常复杂且精妙的设计,想要了解其皮毛也是非常困难的,这并不意味之探究一下Docker的基本原理是没有意义的,恰恰相反,这可以让使用者操作的时候,更清楚自己在干什么。 #### 4.1 总体架构 Docker是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker以及一整套RESTful API。从下图可以看出,整个架构有几个重要的组成部分,Client,Docker Host以及Registry,其中Docker Host内部又包括Images和Containers,**这样看,Docker更像是一个简易版的操作系统**。 ![docker_frame](/img/posts/docker_frame.jpg 'docker_frame') - 这里的**客户端**指的是操作Docker的角色,其实就是宿主机本身; - **Host主机(Docker引擎)**指的是一个物理或者虚拟的机器用于执行Docker守护进程和容器; - **Images镜像**就是一个Linux的文件系统(Root FileSystem),这个文件系统里面包含可以运行在Linux内核的程序以及相应的数据,是一个只读文件; - 通过镜像启动一个**容器**,镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 - **Volume数据卷**是用来将数据持久化到我们宿主机上,与容器间实现数据共享,简单的说就是将宿主机的目录映射到容器中的目录,应用程序在容器中的目录读写数据会同步到宿主机上 - **Registry 注册中心**和软件源中心一样,统一向公众提供镜像服务,Registry分为公共和私有两种 #### 4.2 Docker网络 当项目大规模使用 Docker时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理,容器隔离。为了让容器间通讯更加高效,我们有必要深入了解Docker网络知识,以满足更高的网络需求。安装Docker以后,会默认创建三种网络,可以通过`docker network ls`查看,除了这三种还有一种container模式: ```bash > docker network ls NETWORK ID NAME DRIVER SCOPE de544da1aa64 bridge bridge local e9d574ec50b4 host host local edd7bc64c9d3 none null local ``` - Bridge:默认模式,为每个容器分配设置IP - Host:相当于Vmware中的NAT模式,与宿主机在同一个网络中,但没有独立IP地址 - None:不为Docker容器进行任何网络配置,需手动操作网卡、IP、路由等信息 - Container:一种特殊host网络模式,处于这个模式下的Docker容器会共享一个网络环境,这样两个容器之间可以使用localhost高效快速通信。 一般情况下,使用默认就可以了,当然也可以手动配置区别于docker0的网桥,详见[自定义网桥](https://docker-practice.github.io/zh-cn/advanced_network/bridge.html),另外如有想手动指定网络以及IP地址,可以使用如下指令创建一个自定义网络类型,运行Docker的时候手动指定即可。 ```bash docker network create -d bridge --subnet=172.172.0.0/24 --gateway 172.172.0.1 inner docker run -idt --name=nginx --network=inner --ip=172.172.0.100 nginx:1.14-alpine ``` #### 4.3 Docker VS VM > **Docker的误解:Docker是轻量级的虚拟机** Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问Docker守护进程。Docker守护进程从客户端接受命令,并按照命令,管理运行在主机上的容器。一个Docker容器,是一个运行时环境,可以简单理解为进程运行的集装箱。 ![docker_vs_vm](/img/posts/docker_vs_vm.png 'docker_vs_vm') Docker和KVM都是虚拟化技术,VM(VMware)在宿主机器、宿主机器操作系统的基础上创建虚拟层、虚拟化的操作系统、虚拟化的仓库,然后再安装应用;Container(Docker容器),在宿主机器、宿主机器操作系统上创建Docker引擎,在引擎的基础上再安装应用。它们的主要差别: 1. Docker 有着比虚拟机更少的抽象层 2. Docker 利用的是宿主机的内核,VM需要的是Guest OS 3. Docker 容器很快,启动和停止可以在秒级实现,这相比传统的虚拟机方式要快得多 4. Docker 容器对系统资源需求很少,一台主机上可以同时运行数千个Docker容器。 5. Docker 通过类似Git的操作来方便用户获取、分发和更新应用镜像,指令简明,学习成本较低。 6. Docker 通过Dockerfile配置文件来支持灵活的自动化创建和部署机制,提高工作效率。 7. Docker 容器除了运行其中的应用之外,基本不消耗额外的系统资源,保证应用性能的同时,尽量减小系统开销。 8. Docker 利用Linux系统上的多种防护机制实现了严格可靠的隔离,引入了安全选项和镜像签名机制,极大地提高了使用Docker的安全性。 ## 四、常用指令 目前看来,`docker`和`systemctl`命令比较相似,好的方面是,指令功能从名称上看比较明确,使用起来相对比较顺手,不好的方面是,两者都有大量的子命令,虽然不必所有都掌握甚至了解,但还是挺唬人的。以使用过程中遇到的问题的顺序,将常用的命令汇总如下: ```bash docker info # 查看docker相关信息 docker version # 查看docker版本号 docker pull mysql:latest # 拉取最新版本镜像 # 命令行运行,指定端口和目录映射 docker run -d --restart=always -e SIGNUPS_ALLOWED=false \ --name vaultwarden \ -v /opt/webdav/data/vaultwarden/:/data/ \ -p 8112:80 vaultwarden/server:latest docker images # 列出已有镜像 docker image ls # 列出已有镜像 docker image rm nginx:latest # 删除指定镜像 docker rmi nginx:latest # 删除指定镜像 docker start/stop/restart a148c6fec026 # 启动、停止、重启容器 docker ps -a # 查看所有容器状态 docker exec -it a148c6fec026 /bin/bash # 进入a148c6fec026所代表的容器,并执行相关命令 docker search mysql # 搜索mysql的docker镜像 docker rm a148c6fec026 # 删除a148c6fec026所代表的容器 docker rename old new # 重命名容器 docker logs -f -t --tail 1000 2ab447816a66 # 查看2ab447816a66所代表的容器最近1000条日志 docker cp outer_path 2ab447816a66:inner_path # 向容器内拷贝文件 docker cp 2ab447816a66:inner_path outer_path # 向容器外拷贝文件 ``` ![docker_mindmap](/img/posts/docker_mindmap.png 'docker_mindmap') ## 参考文档 - [Debian 11/Ubuntu 22.04安装Docker以及Docker Compose教程](https://u.sb/debian-install-docker/) - [Docker 架构及工作原理](https://www.docker.org.cn/docker/192.html) - [Docker Hub:官方Registry](https://hub.docker.com/) - [☆ Docker — 从入门到实践](https://yeasy.gitbook.io/docker_practice/)