容器改变世界
[TOC]
容器改变世界
1 虚拟化与容器
容器和虚拟机是两种不同的虚拟化技术,它们各有优缺点,具体如下:
容器(Container):
优点:
- 快速启动:容器是基于宿主机操作系统内核的虚拟化技术,因此启动速度非常快,可以在几秒钟内启动。
- 轻量级:容器可以共享宿主机的操作系统内核,因此容器的资源占用相对较少。
- 易于管理:容器可以通过容器编排工具进行集中管理,可快速部署、扩展和升级。
- 更高的性能:由于容器直接运行在宿主机上,因此不需要额外的虚拟化层,可以获得更高的性能。
缺点:
- 不同宿主机的差异性:容器的应用程序运行在宿主机的操作系统内核上,因此如果在不同的宿主机上运行,则可能会受到宿主机的差异性影响。
- 安全性问题:如果容器中的一个应用程序被攻击,则可能会影响容器中运行的其他应用程序。
- 网络配置较为复杂:在多个容器之间建立网络连接和配置网络规则比较复杂。
虚拟机(Virtual Machine):
优点:
- 可以在不同的操作系统上运行:虚拟机可以模拟出一个完整的操作系统环境,可以在不同的操作系统上运行。
- 隔离性:不同的虚拟机之间是完全隔离的,即使一个虚拟机被攻击,也不会影响其他虚拟机的运行。
- 更安全:由于虚拟机之间是隔离的,因此安全性相对较高。
- 网络配置相对容易:虚拟机之间建立网络连接和配置网络规则相对容易。
缺点:
- 启动速度慢:虚拟机需要启动完整的操作系统,因此启动速度相对较慢。
- 资源占用较高:每个虚拟机都需要完整的操作系统和应用程序支持,因此资源占用相对较高。
- 管理和部署较为繁琐:虚拟机需要进行操作系统和应用程序的管理和维护,因此相对繁琐。
1.1 虚拟化
虚拟化操作系统
1.2 容器
IaaS、 PaaS、 SaaS 和 CaaS 是不同类型的云计算服务
IaaS (基础设施即服务) : 在 IaaS 中,云提供商通过互联网向客户提供虚拟化的计算资源,如服务器、存储和网络。客户可以使用这些资源来构建和管理自己的 IT 基础设施,包括操作系统和应用程序。IaaS 提供商的例子包括 Amazon Web Services (AWS)、 Microsoft Azure 和 Google Cloud Platform
PaaS (平台即服务) : 在 PaaS 中,云提供商为客户提供一个开发、运行和管理应用程序的平台。该平台包括必要的基础设施,如服务器、存储和网络,以及用于构建、测试和部署应用程序的工具。客户可以专注于编写自己的应用程序,而不必担心管理底层基础设施。PaaS 提供商的例子包括 Heroku、 Google App Engine 和 Microsoft Azure。
SaaS (Software as a Service) : 在 SaaS 中,云提供商通过互联网提供软件应用程序,通常是以订阅为基础。客户可以通过网络浏览器或其他客户端软件访问软件,而无需自己安装和维护软件。SaaS 提供商的例子包括 Salesforce、 Zoom 和 Dropbox。
CaaS (Container as a Service) : 在 CaaS 中,云提供商为客户提供了一个管理和编排容器的平台。容器是打包应用程序及其依赖项的轻量级方法,使其更容易部署和管理。CaaS 平台为客户部署和管理容器提供了必要的基础设施和工具,而不必管理底层服务器和网络。CaaS 提供者的例子包括 Amazon Elastic Container Service (ECS)、 Google Kubernetes Engine (GKE)和 Microsoft Azure Container Instances (ACI)。
2 docker容器
2.1 docker容器介绍
1)镜像,容器,应用关系
2.2 docker登录
1)docker官方文档
2)docker hub登录
第一次登录,需要注册账号,注册完账号点击sign in登录,登录进去,在搜索框里面选择自己需要的镜像即可
2.3 容器架构
1)容器C/S架构⭐⭐⭐
- 客户端
- 服务端
- 远程镜像仓库
2.4 安装docker
1)配置docker清华源
- 清华源
# 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 下载centos/redhat版本repo文件
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 软件仓库地址替换为清华源
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
华为云
华为云服务器,centos7.9系统安装docker-ce配置repo源,云服务器不需要配置镜像加速
阿里云docker-ce源
2)安装docker-ce
sudo yum makecache fast
sudo yum install docker-ce
3)设置镜像加速
- 阿里云配置镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://krtjlnjl.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl enable docker --now
4)检查docker
yum list |grep docker
或
rpm -qa | grep docker
2.5 docker命令使用
1)查看docker信息
# 查看docker信息
docker info
# 查看docker版本
docker version
2)拉取镜像
docker pull
3) 查看本地镜像
docker images
4)运行容器
案例1-下载hello-world镜像并运行
docker run hello-world
案例2-下载nginx:alpine镜像并运行
# 容器命名不符合命名规范,包含空格
docker run -d -p 80:80 --name "nginx container by rhythm" nginx:alpine
# 正确的容器名 下划线_连接
docker run -d -p 80:80 --name "nginx_container_by_rhythm" nginx:alpine
# 开启linux内核端口转发
[root@docker01 ~]# tail -1 /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@docker01 ~]# cat /etc/sysctl.conf
net.ipv4.ip_forward = 1
# 从/etc/sysctl.conf读取值,并立即生效
[root@docker01 ~]# sysctl -p
net.ipv4.ip_forward = 1
# 查看docker run帮助
docker run --help
# 查看docker run帮助
man docker run
2.6 docker镜像命令⭐⭐⭐
1)拉取镜像
案例3-拉取镜像nginx:1.22-alpine
# 默认下载latest版本镜像
docker pull nginx:latest
docker pull hello-world
# 指定下载nginx:1.22版本 alpine系统
docker pull nginx:1.22-alpine
2)查看镜像
docker image ls 或 docker images
3)查找镜像
# 命令行搜索
docker search nginx
# docker hub官网搜索
hub.docker.com
4)推送镜像
docker push sweetpage/nginx
5)save保存镜像
sl大法
# 保存hello-world镜像
docker image save hello-world:latest -o hello-world.tar
# 批量导出所有镜像
[root@docker01 ~]# docker images | awk 'NR>1{print "docker save "$1":"$2" -o " $1"_"$2".tar"}' |bash
# 逗号,在awk拼接语句中,输出时使用空格替代
docker images | awk 'NR>1{print "docker save "$1":"$2",-o,"$1"_"$2".tar"}' |bash
6)load加载镜像
# 加载hello-world镜像
docker image load -i hello-world.tar
7)镜像打tag标签
# 可以看到新生成的tag和原tag对应的image id是一样的,类似硬链接
docker image tag hello-world:latest hello-world:rhythm
8)查看镜像内部详细信息
# docker inspect和docker images中镜像id对应关系 <ID:feb5d9fea6a5 前12位对应镜像id>
docker inspect hello-world:latest
9)删除镜像
docker rmi 三种删除镜像标签方法:
- 基于镜像名 :docker rmi centos
- 基于tag标签名 :docker rmi centos:7
- 基于镜像ID :docker rmi 08f7eebd39d6
# 根据镜像标签删除镜像
docker rmi <REPOSITORY>:<TAG>
# 删除镜像centos-php-mariadb-docfile-yum:latest
[root@docker01 ~]# docker rmi centos-php-mariadb-docfile-yum:latest
Untagged: centos-php-mariadb-docfile-yum:latest
强制删除镜像
💁♂️提示:如果您要删除正在使用的 Docker 镜像或标签,则需要先停止使用该镜像或标签的容器。否则,Docker 将拒绝删除正在使用的镜像或标签,但是可以使用-f来强制删除镜像
-f 强制删除镜像
# 删除镜像
docker image rm hello-world:latest或 docker rmi nginx:alpine
# 提示无法移除镜像参考的镜像仓库,容器再使用参考的镜像时
# -f强制删除镜像
docker image rm -f nginx:alpine
2.7 docker容器命令⭐⭐⭐
容器:运行的镜像就是容器,1个容器相当于1个进程
容器相关命令,支持tab键补全
1)运行容器(run)
当使用
docker run
命令启动容器时,Docker底层会执行以下几个主要步骤:
- 创建容器:Docker会创建一个新的容器实例,该实例包含容器的文件系统、网络和其他配置。
- 创建命名空间:Docker会使用Linux的命名空间技术,创建一个独立的进程命名空间,使容器内的进程与宿主机器上的进程相隔离。
- 分配文件系统:Docker会为容器分配一个独立的文件系统,包括容器内部的文件和目录。这个文件系统可以是基于镜像的,也可以是可写的,具体取决于你如何启动容器。
- 分配网络:Docker会分配一个独立的网络命名空间,为容器提供一个独立的网络栈。Docker还会为容器分配一个IP地址,并将其映射到宿主机器上的端口,使得容器可以被访问。
- 启动容器进程:Docker会在容器内部启动一个进程,这个进程通常是应用程序或服务。在启动进程之前,Docker会应用容器的配置,并将它们传递给容器内部的进程。
总的来说,
docker run
命令会执行一系列的步骤,将容器和宿主机器之间的资源和隔离度进行配置,使得容器能够运行并且与宿主机器进行交互。docker run == docker pull + create + start
- docker pull 拉取镜像
- docker create 创建容器
- docker start 启动容器
- docker stop 停止容器
- docker kill 杀死容器
- docker restart 重启容器
# 使用nginx:alpine镜像运行容器,容器名rhythm_nginx_alpine1
docker run -d -p 80:80 --name "rhythm_nginx_alpine1" nginx:alpine
# -d选项 后台运行daemon模式,不加-d,可能运行容器的时候,在前台,会有容器内部信息输出
# -p选项 端口映射,实际是通过iptables防火墙做的nat转换,访问host主机的80端口就相当于访问容器的80端口
# -p选项 端口范围:端口范围 例如: -p 80-84:80-84 宿主机的80到84端口,对应docker容器的80-84
# --name 设置容器名,注意命名规范不能使用空格,可以使用_连接字符串
# 创建容器
docker create --name "nginx_alpine_create_container" nginx:alpine
# 启动容器
docker container start nginx_alpine_create_container
2)查看运行的容器(ps 或ps -a)
# 查看运行中的容器
docker ps
等价于
docker container ps
# 查看所有状态的容器
docker ps -a
# 只查看容器的ID
docker ps -q
# 浏览器访问nginx:alpine镜像运行的容器
http://www.rhythmcloud.cn:8088/
3)停止运行的容器(stop)
# 停止运行中的容器
docker container stop rhythm_nginx_alpine1
4)删除容器(rm)
# 删除容器
# docker rm 容器ID或容器名
docker rm rhythm_nginx_alpine1
或者
docker container rm 容器ID或容器名
# 选项 -f 强制删除容器(包括运行的容器,危险操作,容易导致容器内服务运行的数据丢失)
docker rm -f 容器ID
# 强制删除所有容器
docker rm -f `docker ps -q`
5)创建centos容器,并进入(-it)
# 新建1个centos容器,并进入容器
docker run -it --name "rhythm_centos" centos:latest
# 查看容器内进程信息
ps -ef
docker run -it --name "rhythm_centos7.9_2009" centos:centos7.9.2009
6)查看容器信息(stats|inspect|top)
docker stats 容器名 # 查看容器id,name,cpu,mem/limit mem% net i/o block i/o pid进程数
docker inspect 容器名 # 查看容器详细信息
docker top 容器名 # 查看容器中的进程
7)持续运行容器(-itd)
docker run -itd --name "rhythm_centos7.9_2009" centos:centos7.9.2009 /bin/bash
8)连接进入已经启动的容器(exec)
- docker exec
# 多个tty终端执行exec连接到同1个容器,执行操作,在所有终端上是相互独立的
docker exec -it 运行的容器名 /bin/bash或/bin/sh
# nginx:alpine镜像起的容器,没有/bin/bash命令,可以使用/bin/sh登录
docker exec -ti rhythm_nginx_alpine1 /bin/bash
# 使用/bin/sh正常登录容器
docker exec -ti rhythm_nginx_alpine1 /bin/sh
- docker attach
# 多个tty终端执行attach连接到同1个容器,执行操作,在所有终端上是同步的,不是相互独立的
docker container attach rhythm_centos7.9_2
8)宿主机拷贝文件到容器(容器到宿主机cp)
- 宿主机拷贝文件到容器
# 下载百度首页,并保存为index.html
curl -o index.html www.baidu.com
# 拷贝index.html到容器
docker container cp index.html rhythm_nginx_alpine1:/usr/share/nginx/html/index.html
# 宿主机curl访问本地80端口
curl localhost
# 浏览器访问容器主页
http://docker.rhythmcloud.cn/
# 更多帮助
docker container cp --help
- 拷贝容器文件到宿主机
docker container cp rhythm_nginx_alpine1:/usr/share/nginx/html/index.html /tmp/index.html
9)生成镜像(commit)⭐⭐⭐
docker commit: 在学习docker file之前自定义镜像方法
# 上传静态网站代码restart-new.zip
# lrzsz上传静态网站代码到docker01
# 拷贝网站代码到容器内,并解压
docker container cp restart-new.zip rhythm_nginx_alpine1:/app/code/restart
# 修改nginx配置文件
vi /etc/nginx/conf.d/default.conf
# nginx容器配置文件
/app/code/restart # cat /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name restart.rhythmcloud.cn;
root /app/code/restart;
location / {
index index.html;
}
location ~* \.css$ {
root /app/code/restart/css;
}
}
# 检查语法,并重启nginx
nginx -t
nginx -s reload
# 浏览器访问docker01的80端口
http://docker.rhythmcloud.cn/
- docker commit
# 将指定的容器使用docker commit生成指定的镜像
# 语法格式:docker container commit 或 commit 容器名 镜像名(命名空间+系统+版本信息)
docker commit rhythm_nginx_alpine1 nginx:alpine-restart-v1
# 通过commit新生成的镜像运行容器81端口
docker run -d -p 81:80 --name "rhythm-nginx-commit-create" nginx:alpine-restart-v1
# 浏览器访问81端口
http://docker.rhythmcloud.cn:81/
2.8 端口映射
端口映射的作用:实现外部人员访问宿主机内的容器
-p参数
#端口映射的本质就是通过iptables防火墙,给nat表添加了一条DOCKER链规则,具体如下:
#将docker宿主机上非docker0网卡(宿主机其他物理网卡来的流量)的tcp协议,tcp数据包,目的地是8888端口的流量转发到容器内的ip地址172.17.0.10和端口80上
#docker宿主机需要启用ip转发功能,确保流量在宿主机和容器正确转发
#iptables规则说明:
iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 8888 -j DNAT --to-destination 172.17.0.10:80
1)1对1端口映射
# -p 80:80 宿主机80端口:容器80端口
# -p :80 宿主机随机端口:容器80端口
# -p 80-84:8080-8084 宿主机80-84端口:容器8080-8084端口(端口范围)
docker run -d -p 80:80 --name "nginx_alpine_rhythm_v1" nginx:alpine-restart-v1
docker run -d -p :80 --name "nginx_alpine_rhythm_v2" nginx:alpine-restart-v1
docker run -d -p 80-84:8080-8084 --name "nginx_alpine_rhythm_v3" nginx:alpine-restart-v1
2)映射多个端口
多个-p映射多个端口,端口不连续时
docker run -d -p 80:80 -p 443:443 --name "容器名" 镜像名
3)ip绑定端口
只允许指定ip端口访问,出于安全要求
# 宿主机的内网网卡+81端口172.16.1.81:81:容器的80端口 容器名 镜像名
docker run -d -p 172.16.1.81:81:80 --name "nginx_alpine_rhythm_81_80" nginx:alpine
[root@docker01 ~]# ss -lntup |grep 81
tcp LISTEN 0 128 172.16.1.81:81 *:* users:(("docker-proxy",pid=43063,fd=4))
# 使用curl访问
curl 172.16.1.81:81
curl localhost:81
curl 10.0.0.81:81
2.9 数据卷挂载
数据卷挂载的作用:
容器删除后,容器中的数据就被丢失了,如何持久化存储,就引入了数据卷挂载,实现将宿主机的文件或目录挂载到容器中,修改宿主机的文件就修改了容器运行时使用的文件
将宿主机文件和目录挂载到容器中,就不需要单独进入容器,修改容器内的文件和目录,只需要修改宿主机中的即可
多个容器,
数据卷挂载命令:docker run -v参数
1)挂载宿主机主页文件到容器
# 宿主机创建主页文件
mkdir -p /app/docker/code
echo "volume test in container" >> index.html
# 挂载宿主机主页文件到容器(一行)
docker run -d -p 80:80 --name "nginx_alpine_volume" -v /app/docker/code/index.html:/usr/share/nginx/html/index.html nginx:alpine
# 将上面一行写成多行(使用\续行符,后面不能跟空格,直接回车换行)
docker run -d -p 80:80 --name "nginx_alpine_volume" \
-v /app/docker/code/index.html:/usr/share/nginx/html/index.html \
nginx:alpine
# 浏览器访问
http://docker.rhythmcloud.cn/
# 使用echo追加内容(echo修改文件内容之后,不会修改文件的inode号)
echo "rhythm volume test in container" >> index.html
# 浏览器访问
http://docker.rhythmcloud.cn/
2)inspect查看volume挂载信息
docker inspect nginx_alpine_volume | jq .[].HostConfig.Binds
案例1:挂载代码目录,配置文件和目录⭐⭐⭐
挂载,映射多个文件+目录使用多个-v选项
# 运行容器,使用-v挂载, --restart=always表示重启后,容器会自启动
docker run -d -p 81:80 --name "restart_volume" \
-v /app/docker/restart/code/:/app/code/restart \
-v /app/docker/restart/conf/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v /app/docker/restart/conf/nginx/conf.d/:/etc/nginx/conf.d/ \
--restart=always \
nginx:alpine
# 浏览器访问容器81端口
http://docker.rhythmcloud.cn:81/
# 在宿主机修改容器的restart.conf配置文件,给css文件添加expires时间
# F12打开开发工具-开启响应头cache-control,查看超时时间
[root@docker01 /app/docker/restart/conf/nginx/conf.d]# cat restart.conf
server {
listen 80;
server_name restart.rhythmcloud.cn;
root /app/code/restart;
location / {
index index.html;
}
location ~* \.css$ {
root /app/code/restart/css;
expires 10d;
}
}
# 浏览器刷新,F12开发工具查看
案例2:创建数据卷空间
两种方法查看容器中日志:
访问日志格式是软链接格式的,可以在容器外使用docker logs查看
访问日志是文件的使用head tail cat等查看,也可以通过创建软链接,实现docker logs查看
# 创建数据卷rhythmlogdata
docker volume create rhythmlogdata
# 查看数据卷
docker volume ls
# 查看数据卷路径:/var/lib/docker/volumes/数据卷名/
ls /var/lib/docker/volumes/rhythmlogdata/
# 运行容器,挂载rhythmlogdata到nginx:alpine容器的日志目录/var/log/nginx
docker run -d --name "datavolume_nginx_alpine" -v rhythmlogdata:/var/log/nginx/ -p :80 nginx:alpine
# 查看数据卷挂载信息
ls -al /var/lib/docker/volumes/rhythmlogdata/_data
lrwxrwxrwx 1 root root 11 Dec 30 2021 access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 Dec 30 2021 error.log -> /dev/stderr
# 查看数据库容器日志,查看nginx日志
# 格式:docker logs 容器名
# --since 加时间,表示至从某1个时间到现在,例如 --since 120m,表示最近的120分钟的日志
docker logs mariadb --since 120m
docker logs nginx_alpine --since 120m
# 查看nginx_alpine容器内日志的时间不正确(需要修改时区)
# 具体查看chatgpt解决方案
[root@docker01 ~]# docker logs nginx_alpine --since 120m
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/03/27 08:30:41 [notice] 1#1: using the "epoll" event method
2023/03/27 08:30:41 [notice] 1#1: nginx/1.21.5
2023/03/27 08:30:41 [notice] 1#1: built by gcc 10.3.1 20211027 (Alpine 10.3.1_git20211027)
2023/03/27 08:30:41 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64
2023/03/27 08:30:41 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/03/27 08:30:41 [notice] 1#1: start worker processes
2023/03/27 08:30:41 [notice] 1#1: start worker process 32
2023/03/27 08:31:05 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2023/03/27 08:31:05 [notice] 32#32: gracefully shutting down
2023/03/27 08:31:05 [notice] 32#32: exiting
2023/03/27 08:31:05 [notice] 32#32: exit
2023/03/27 08:31:05 [notice] 1#1: signal 17 (SIGCHLD) received from 32
2023/03/27 08:31:05 [notice] 1#1: worker process 32 exited with code 0
2023/03/27 08:31:05 [notice] 1#1: exit
- 容器时区问题
# nginx:alpine容器时间修改为中国时间
docker exec -it <container_name_or_id> sh
apk add --no-cache tzdata
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
# 退出容器再进,执行时间命令查看
date
案例3:启动1个mariadb容器
具体启动mariadb容器实例,可以查看hub.docker.com中mariadb官方镜像使用说明
# 运行mariadb容器
# 运行时需要加-e或--env环境变量,否则容器会自动停止
docker run --detach --name some-mariadb --env MARIADB_ROOT_PASSWORD=1 mariadb:latest
# 进入容器启动mysql
docker exec -it some-mariadb /bin/bash
mysql -uroot -p1
// 2 运行容器时,直接加mysql -uroot -p1
docker run -d --name maraidb -e MARIADB_ROOT_PASSWORD=1 mariadb:latest
# 直接接mysql命令进入数据库,不需要先进入/bin/bash后执行mysql命令
docker exec -it maraidb mysql -uroot -p1