242 lines
13 KiB
Markdown
242 lines
13 KiB
Markdown
---
|
||
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的角色,其实就是宿主机本身;
|
||
- **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和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 # 向容器外拷贝文件
|
||
```
|
||
|
||

|
||
|
||
## 五、参考文档
|
||
|
||
- [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/)
|
||
|