docker 快速入门实操教程

docker 快速入门实操教程

docker,启动!

如果安装好docker不知道怎么使用,不理解各个名词的概念,不太了解各个功能的用途,这篇文章应该会对你有帮助。

前置条件:已经安装docker并且docker成功启动。

最终目的:使用docker替换本地安装的程序并迁移数据(redis、MySQL)。

理解概念

docker官方提供了一个分发平台DockerHub,可以从上面拉取已经提供好的镜像直接构建容器运行。

这个过程会涉及到docker的一些概念,在刚接触的时候比较抽象,这里以烘焙出一个蛋糕为例子说明一下:

  • Dockerfile: 蛋糕的配方。配方上详细列出了需要的材料(如面粉、糖、鸡蛋)以及烘焙的步骤(如先将面粉和糖混合,然后加入鸡蛋搅拌)。
  • 镜像(Image): 按照配方做出了一个半成品蛋糕,这就是蛋糕的"镜像" 。这个蛋糕可以被任何人复制,每一个复制品都会和原蛋糕一模一样。
  • 容器(Container): 将半成品蛋糕烘焙后,得到一个可食用的蛋糕。可以根据同一个镜像制作出很多个完全一样的蛋糕,也可以在烘焙时自己加一些材料。每个蛋糕都是独立的,和其他蛋糕没有关联。

所以从DockerHub拉取镜像并且跑起来的过程就可以理解为:

  1. 镜像提供者编写好了配方( Dockerfile ),将其制成( 构建 )了半成品蛋糕( 镜像 )。
  2. 用户购买( 拉取 )这个半成品蛋糕。
  3. 烘焙( 创建 )后得到了一个可食用的蛋糕( 容器 ),食用蛋糕( 运行容器 )。
  4. 通常创建容器和运行容器都会归拢在同一步:创建并运行。

还有另外两个概念,在使用过程中不会接触到,但是对编写Dockerfile会很有帮助:

  • 层(Layers): 根据配方制作蛋糕的每一个步骤(如把面粉和糖混合在一起,这是第一层;加入鸡蛋搅拌,这就是第二层)。层这个概念在使用时并不重要,甚至不会接触到,可以在自己编写Dockerfile时再去深入理解。
  • 缓存(Cache): 现在有两个配方,配方中都有一个步骤( )是购买A型号烤箱,根据第一个配方制作时已经买好了该烤箱,那么在根据第二个配方制作时就可以复用该烤箱以节省时间,这就是缓存的概念。

创建容器

每一步都提供了docker desktop(简称桌面版)的操作截图和终端命令,桌面版界面友好适合上手,终端命令的可操作性更强。

从DockerHub拉取MySQL镜像到本地,这一步可能会因为网络原因失败或者很慢,可以配置其他镜像源或者使用代理,网上教程很多。

如果不想使用桌面版,也可以选择通过终端拉取

bash 复制代码
docker pull mysql:latest

其中 Tag 中的 latest ,这表示这是最新的版本,如果有需要,也可以去找指定的版本拉取。

docker pull 这一步并不是必须的,如果本地没有你指定的镜像,在 docker run 时会自动拉取。

拉取完成后,通过 docker run 创建容器并运行。MySQL的容器直接启动会失败,提示需要配置密码,所以需要先进行一些配置。

该操作对应的终端命令

bash 复制代码
docker run --name mysql_8.3.0 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:latest
# --name 容器名称
# -p 宿主机端口:容器内部端口
# -e 环境变量
# -d 后台运行

容器名称:可以随意定义,但是不能重复,这里使用的是 镜像名_版本号 的方式。

端口映射:将宿主机的 3306 端口映射到容器的 3306 端口,宿主机上的其他进程通过该端口才能访问到容器内的服务。如果不配置端口映射,则只能在容器内部访问服务或通过虚拟网络让容器可以相互通信。所以即使redis是开箱即用的,通常也还是会为其配置端口映射。

如果宿主机已经运行了MySQL并且占用了 3306 端口,需要先停掉宿主机的MySQL服务或者选择其他未被占用的端口。

环境变量:配置 MYSQL_ROOT_PASSWORD 的作用则是指定root用户的密码,这是由MySQL的镜像创建者约定好的,不同的镜像配置项会有所不同。

至此,容器已经成功创建并且运行起来了。

启停容器

容器已经创建好后就不再适用于 docker run 命令了, docker run 命令主要是用于创建新的容器并运行,如果需要启动已经存在的容器,则使用 docker start 命令。

终端命令

bash 复制代码
# 启动容器
docker start mysql_8.3.0

# 停止容器
docker stop mysql_8.3.0

# 重启容器
docker restart mysql_8.3.0

发现问题

现在MySQL容器已经成功运行了,但是遇到了如下几个问题

  • 如何获取到镜像中程序具体的版本
  • 如何将数据持久化到本地,并且让电脑和宿主机比较方便的交换文件
  • 容器没有持续运行/自动关闭

查看镜像内软件版本号

因为MySQL镜像的 Taglatest ,并没有明确指出具体的版本号,所以需要手动查看,两种方案:

1、进入容器终端查看版本

进入容器的终端

执行该软件查看版本的指令,比如MySQL的就是

bash 复制代码
mysql -V

终端命令

bash 复制代码
docker exec mysql_8.3.0 mysql -V
# exec 在容器中执行命令

但是问题就来了,如果需要版本号是为了给容器命名,这种方案需要先运行容器,将容器删除,再重新创建容器,很麻烦。

2、通过镜像中的指令查看

通常Dockerfile中会指明版本号,我们可以直接点开镜像查看

终端命令

bash 复制代码
docker inspect mysql:latest

这个方式虽然比较方便,但是需要进行推测,并非一定正确。

数据持久化保存

如果数据不持久化保存的话,当容器关闭后,数据也就丢失了。

docker为持久化提供了三种方式:

  • bind mount 把宿主机目录映射到容器内,双向文件传递。

    适合文件变动比较频繁的场景,比如存放代码、配置文件,传递文件到容器内,从容器内取出文件等。

  • volume(卷) 由容器创建和管理,创建在宿主机中,官方推荐,更高效,Linux 文件系统。

    宿主机上并不能操作卷中的数据,适合存储不需要关心的数据,如数据库数据。

  • tmpfs mount 适合存储临时文件,存宿主机内存中。不可多容器共享。

MySQL镜像指定了一个 volume 卷用于持久化数据,但是如果创建容器时没有主动指定卷的名字,其就是一个匿名卷,匿名卷会随机生成一个名称,当挂载该卷的容器被删除后,该卷也会被删除。

在docker中,如果只指定了名字则是 volume ,如果指定了具体目录就是 bind mount

所以在创建容器时指定一下卷的名字,同时为了方便传递文件到容器中(如将sql文件),还通过 bind mount 方式映射了一个宿主机的本地目录。

终端命令

bash 复制代码
docker run --name mysql_8.3.0 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -v D:\mount:/pc_mount -v=mysql_volume:/var/lib/mysql -d mysql:latest
# -v 挂载目录

在挂载目录时,如果你指定的目录不存在于容器中,则会自动创建,这里的 /pc_mount 目录就会自动被创建。

指向的 /var/lib/mysql 目录也可以通过Dockerfile查看,当指定的 volume 路径和Dockerfile指向的路径一致,则该卷就不会被挂载为匿名卷了。

这样容器中的数据就会一直保存在宿主机中,即使容器被删除也不影响。

保持容器运行

当在桌面版运行ubuntu等容器时,会发现容器启动后就停止了,进入 Exited 状态,如果想要容器持续运行,就需要需要在容器内部执行一个持续运行的进程。这里桌面版已经不能满足需求了,需要用到终端执行。

终端命令

bash 复制代码
docker run -it --name ubuntu_22.04 ubuntu:latest
# -i 能够接受用户输入
# -t 分配一个虚拟的终端或控制台

通过 -t 指令可以让容器持续运行不会关闭, -i 指令可以让打开的控制台能够接受用户输入。

迁移数据

现在需要将宿主机中MySQL数据迁移到容器中,打算采用navicat的数据迁移工具,那么就需要同时运行两个数据库,端口同为3306会冲突,宿主机上MySQL端口改起来并不方便,容器创建后端口也不能修改,那么就可以使用数据挂载的方式。

迁移方案:

  1. 停止运行端口为3306的MySQL容器。
  2. 新创建一个MySQL容器,端口指定为3305(或其他任意未被占用的端口),指定 volume 卷的名称和端口3306的容器一致。
  3. 迁移数据。
  4. 删除端口为3305的容器,运行端口为3306的容器,发现数据迁移成功。

虚拟网络

每个docker容器都运行在自己的环境中,互不干扰,所以上述内容中都依赖宿主机的端口映射进行容器通信。但是有些时候我们只要让这个项目能在宿主机上访问到,并不在意其所依赖的服务是否能够被宿主机操作和管理。就可以通过docker提供的虚拟网络实现容器之间的通信,再映射项目入口到宿主机即可。

桌面版并没有为虚拟网络提供较好的GUI支持,所以通过命令行完成虚拟网络的配置。

查看已存在的虚拟网络

bash 复制代码
docker network ls

默认已经存在了三个虚拟网络,这是由docker创建的,对应着不同的网络驱动类型,驱动类型的区别如下:

  • Bridge网络: 默认值。容器在独立的网络空间运行,可以相互通信并访问外部网络。容器内服务能通过端口映射被外部访问。
  • Host网络: 容器共享宿主机的网络空间,不再需要端口映射,直接使用宿主机的端口。这种模式提供了最高的网络性能,但是失去了隔离性。
  • None网络: 容器拥有自己的网络空间,但不配置任何网络接口。它只有本地回环接口,没有任何外部网络访问能力,提供了最高的网络隔离性。

创建名为 test_net 的网络

bash 复制代码
docker network create test_net

在该网络下创建两个容器

bash 复制代码
docker run --name redis_temp --network=test_net -d redis:latest
docker run --name redisinsight -p 8001:8001 --network test_net -d redislabs/redisinsight:latest

创建了redis容器,但是并没有为其映射端口。所以现在在宿主机中并不能访问到这个redis容器。

创建了redisInsight容器并且映射了8001端口,这是一个redis的GUI工具,用于测试是否可以通过工具访问到该redis容器。

访问 http://localhost:8001/ 进入redisInsight的主页,添加一个redis数据库。

在docker内部的DNS服务会自动将容器名称解析为容器对应的IP地址(即容器名称就是域名),所以主机地址填写容器名称即可。

更改已存在的容器的连接的网络

bash 复制代码
docker network connect 网络名称 容器名称

连接成功,这样既可以操作容器内的redis数据,又不会占用宿主机自身的redis应用抢占端口。

结语

至此,你已经掌握了docker的基础操作,后续还有编写 Dockerfile、构建镜像、Docker-Compose等操作,为了避免篇幅过长,打算单开一个文章。

相关推荐
桂月二二4 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes
Smile丶凉轩6 小时前
Docker核心技术和实现原理
运维·docker·容器
清风细雨_林木木6 小时前
Docker使用——国内Docker的安装办法
运维·docker·容器
dessler7 小时前
Docker-Dockerfile讲解(三)
linux·运维·docker
一休哥助手7 小时前
深入理解 Docker 网桥配置与网络管理
docker·容器·eureka
PittDing8 小时前
【更新】Docker新手入门教程2:在Windows系统通过compose创建多个mysql镜像并配置应用
windows·mysql·docker
Mitch3119 小时前
【漏洞复现】CVE-2014-3120 & CVE-2015-1427 Expression Injection
运维·web安全·elasticsearch·docker·apache
m0_7482510810 小时前
docker安装nginx,docker部署vue前端,以及docker部署java的jar部署
java·前端·docker
m0_7482402511 小时前
docker--压缩镜像和加载镜像
java·docker·eureka
lmxnsI12 小时前
docker使用笔记
笔记·docker·容器