docker基本使用与进阶
docker基本使用与进阶
一.前言
在笔者大一学习开发知识的这段时间里,数据库、服务器等基本都是用docker进行容器化部署。随着需要部署的服务越来越多,笔者越发体会到docker的便利与强大(味大,无需多盐),感觉学习docker是很有必要的,于是特撰写此博文来对没有使用过docker的小白进行扫盲,并对docker的功能及命令进行汇总以便后期回顾,让小白快速掌握docker的基本用法。
二.docker简介
摘自百度百科:Docker是一组平台即服务(PaaS)的产品。它基于操作系统层级的虚拟化技术,将软件与其依赖项打包为容器。托管容器的软件称为Docker引擎。Docker能够帮助开发者在轻量级容器中自动部署应用程序,并使得不同容器中的应用程序彼此隔离,高效工作。
通俗来讲,docker是一种成熟的软件部署技术,轻量高效,启动速度快。docker实际上就是将进程和它运行所需要的运行环境打包到一个容器里面,系统给其分配独立的文件系统、进程组和网络资源,并且容器与容器之间互不干扰(大部分如此,其他情况后面会给说明)。使用docker,部署服务将变得更加便捷高效,使你的开发效率得到大幅提升。
三.docker安装
docker是基于Linux操作系统运作的,可以使用虚拟机或云服务器,或在windows系统上装一个WSL来安装使用
WSL官方文档:安装 WSL | Microsoft Learn
docker安装:
在Linux命令行中运行以下命令安装:
1 | curl -fsSL http://get.docker.com -o install-docker.sh |
1 | sudo sh install-docker.sh |
四.docker核心逻辑
**docker镜像&docker容器:**docker镜像就相当于模板,而docker容器就是利用模板来制作的实例,一个镜像可以对应多个容器,你可以对容器添加各种参数或者直接修改容器内置配置文件来实现对容器的定制化
五.常用命令
接下来我将使用mysql作为例子
1.对镜像操作
docker pull
这个命令就是让你从Docker Hub官方仓库拉取一个镜像
Docker Hub官网:Docker Hub Container Image Library | App Containerization
1 | docker pull docker.io/library/mysql:latest |
这行命令代表我要从官方仓库拉取一个最新版本的mysql镜像
**docker.io:**仓库地址registry(Docker Hub就是一个registry),docker.io是Docker Hub的官方仓库,可以省略
**library:**命名空间namespace(作者名),library是官方的命名空间,可以省略
**latest:**标签tag(版本号),如果要获取最新版本镜像,可以省略
仓库地址+命名空间+镜像名=repository(镜像库),一个镜像库中存放了同一个镜像的不同版本
如果拉取镜像时报错,有两个最常见的问题:
无权限——此时需要你在每行命令前面加一个sudo来获取权限执行
网络问题——需要配置国内镜像站,具体可从网上搜索做法
1 | docker pull --platform=xxxxxx mysql |
这行命令中platform参数表示拉取特定CPU架构的镜像
docker images
1 | docker images |
这行命令是让终端列出所有下载过的docker镜像
docker rmi
1 | docker rmi |
rmi(remove image)表示删除镜像,后面可以加镜像名或镜像id进行删除
2.对容器操作
docker run
1 | docker run -d \ |
使用镜像创建并运行容器
–name:自定义容器名称
-d:分离模式,表示让容器在后台执行,容器启动以后日志不会打印到控制台
-p:端口映射
每一个容器都运行在一个独立的虚拟环境中,容器内的网络与宿主机的网络是隔离的,所以默认情况下不能从宿主机中访问到容器内的网络,比如我启动mysql容器但并没有做端口映射,在navicat中输入localhost,端口写3306并不能连接到mysql数据库。但如果我加上-p 3306:3306参数,表明将宿主机的3306端口(冒号前)转发到容器内的3306端口(冒号后),这样访问宿主机3306端口也就相当于访问容器3306端口
-v:挂载卷
-v 宿主机目录:容器内目录(绑定挂载),表示把宿主机与容器的文件目录进行绑定,两个文件夹修改是会互相影响的,这种目录被称为挂载卷。挂载卷可以实现数据的持久化保存,当我们删除容器以后,容器内的数据会一并删除,而当把容器内的数据挂载到宿主机上再删除容器,容器的数据还保存在宿主机上没被删除。
这里有个细节,绑定挂载以后,宿主机的目录会暂时覆盖容器内的目录,也就是说现在容器内目录是空的,为此,我们可以直接修改宿主机目录(比如在宿主机加一个index.html文件来覆盖掉容器内目录的index.html文件)来使宿主机目录非空
-v 卷的名字:容器内目录(命名卷挂载)
1 | docker volume create conf # 挂载卷的名字 |
此命令的作用为创建挂载卷,此时可以直接使用 conf:/etc/mysql/conf.d 来进行挂载
1 | docker volume inspect conf |
执行这行命令可以显示这个挂载卷的信息,从这也可以看到这个挂载卷的真实目录,但进入这个目录需要切换到root用户:
1 | sudo -i |
这种挂载方式docker会把容器的文件夹同步到命名卷里面进行初始化,这样就避免了目录为空的情况
-e:环境变量
这里是将数据库的账号密码作为环境变量传递进去
–name:自定义容器名称
与容器ID等价,更加容易记忆
----------这里还有其他一些参数----------
-it:可以让控制台进入容器进行交互
–rm:当容器停止时就把容器删除
–restart always:只要容器停止了就会立即重启
–restart unless-stopped:唯一区别就是手动停止的容器不会重启
docker ps
1 | docker ps -a |
查看当前正在运行的容器的信息,包括容器ID,镜像名称,容器名称等
-a:查看所有容器
docker stop
1 | docker stop my-mysql |
停止my-mysql容器运行
docker start
1 | docker start my-mysql |
启动my-mysql容器
docker rm
1 | docker rm -f my-mysql |
删除my-mysql容器
-f:强制删除正在运行的容器
docker inspect
1 | docker inspect my-mysql # 或者容器ID |
这里可以在控制台打印容器的详细信息,包括有没有做挂载卷,有没有做端口映射
docker create
1 | docker create -p 3306:3306 mysql |
docker create和docker run命令的区别在于docker create只创建容器,但不启动容器
docker logs
1 | docker logs -f my-mysql # 或者容器ID |
这个命令可以查看容器日志
-f:表示滚动查看日志
docker exec
1 | docker exec -it my-mysql /bin/sh |
exec可以在容器内部执行Linux命令
这行命令可以进入一个正在运行的容器内部,获得一个交互式的命令行环境,容器内部就像是一个独立的Linux操作系统
六.docker技术原理
docker利用linux的Cgroups和Namespaces进行容器化
Cgroups来限制和隔离进程的资源使用,可以为容器进程设置内存、CPU、网络带宽等资源的使用上限,确保容器的资源消耗不会影响到宿主机和其他容器
Namespaces用来隔离进程的资源视图,它使容器只能看到自己内部的进程ID、文件目录和网络资源
容器本质上是一个特殊的进程,但容器内部更像是一个独立的操作系统,每个docker容器都是一个独立的运行环境
七.Dockerfile
Dockerfile是一个详细列出镜像是如何制作的一个文件,我们可以使用Dockerfile制作镜像并把它推送到Docker Hub上去
首先在要打包成镜像的同级目录创建一个Dockerfile文件(注意,没有后缀)
我会用python程序打包来示例
1 | FROM python:3.13-slim # 表示这个镜像是从哪个镜像的基础上构建而来 |
Dockerfile准备好以后就可以开始构建镜像
在命令行运行以下命令
1 | docker build -t 镜像名:版本号 . # 版本号可省略, . 表示在当前文件夹构建 |
然后再Docker Hub上登陆
运行
1 | docker build -t 用户名/镜像名 . |
1 | docker push 用户名/镜像名/ |
八.docker网络
1.桥接模式
桥接模式(Bridge),所有容器默认连接到这个网络,每个容器都分配一个内部IP地址,一般是172.17开头,在这个内部子网里面,容器与容器之间通过内部IP地址互相访问,但是容器与宿主机之间的网络是隔离的,这时候可以使用
1 | docker network create 子网名 |
创建子网,然后可以使容器加入不同子网,同一子网的容器可以互相使用名字或IP进行通信(这就是博文开头所说的其他情况),但跨子网不能通信
1 | docker run --network 子网名 |
–network:指定加入的子网
处在同一子网下的两个容器,a容器没做端口映射,但b容器做了端口映射,此时宿主机网络可以与b容器通信,b容器知道a容器的名字(docker子网有一个DNS机制,可以把名字转换为IP地址),也可以与它通信,所以宿主机便可以间接与a容器进行通信
2.Host模式
这种模式使Docker容器直接功响宿主机的网络,容器直接使用宿主机的IP地址,也就无需进行端口映射,容器内的服务直接运行在宿主机的端口上
3.none模式
none模式也就是不联网
1 | docker network list |
展示所有的Docker网络
1 | docker network rm 子网名 |
删除自定义的子网
九.docker compose
往往一个项目会涉及到前端、后端、数据库的许多模块,如果把它们一个个拉取镜像,一个个创建容器就显得十分麻烦,这时候docker compose就发挥了作用
docker compose(轻量级,适合单机)是docker使用yml文件管理多个容器,可以理解为把多个docker run命令封装到了一个docker compose文件中
1 | docker compose -f /test.yaml up -d |
启动这个文件中定义的所有容器
-f:指定文件
如果docker-compose.yaml文件名改动(比如改成test.yaml),可以使用-f参数来指定文件以防识别不出来
-d是后台运行
1 | docker compose down |
停止并删除容器
1 | docker compose stop |
只停止不删除
1 | docker compose start |
启动容器