首页 > 其他分享 >docker 快速入门实操教程

docker 快速入门实操教程

时间:2024-01-29 18:01:34浏览次数:30  
标签:容器 教程 宿主机 端口 实操 mysql 镜像 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镜像到本地,这一步可能会因为网络原因失败或者很慢,可以配置其他镜像源或者使用代理,网上教程很多。

image-20240128210738711

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

docker pull mysql:latest

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

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

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

image-20240128213738553

该操作对应的终端命令

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 命令。

终端命令

# 启动容器
docker start mysql_8.3.0

# 停止容器
docker stop mysql_8.3.0

# 重启容器
docker restart mysql_8.3.0

发现问题

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

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

查看镜像内软件版本号

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

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

进入容器的终端

image-20240128221006990

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

mysql -V

image-20240128221033165

终端命令

docker exec mysql_8.3.0 mysql -V
# exec 在容器中执行命令

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

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

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

image-20240128220336815

终端命令

docker inspect mysql:latest

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

数据持久化保存

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

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

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

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

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

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

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

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

image-20240128222428479

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

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

image-20240128220629652

终端命令

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指向的路径一致,则该卷就不会被挂载为匿名卷了。

image-20240128224015528

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

保持容器运行

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

终端命令

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支持,所以通过命令行完成虚拟网络的配置。

查看已存在的虚拟网络

docker network ls

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

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

创建名为 test_net 的网络

docker network create test_net

在该网络下创建两个容器

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地址(即容器名称就是域名),所以主机地址填写容器名称即可。

image-20240129172212539

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

docker network connect 网络名称 容器名称

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

结语

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

标签:容器,教程,宿主机,端口,实操,mysql,镜像,docker
From: https://blog.51cto.com/u_16249477/9471669

相关文章

  • docker-compose命令
    docker-compose命令1、基础命令docker-compose命令--help#获得一个命令的帮助docker-composeversion#查看docker-compose版本信息2、构建、卸载docker-composeup-dC#构建启动某个容器docker-composed......
  • docker-compose.yaml相关
    docker-compose.yaml相关Compose和Docker兼容性:Compose文件格式有3个版本,分别为1,2.x和3.x目前主流的为3.x其支持docker1.13.0及其以上的版本常用参数:version#指定compose文件的版本services#定义所有的service信息,......
  • docker-compose部署简单案例
    Dockerfile#设置基础镜像FROMpython:3.7#设置环境变量ENVPYTHONUNBUFFERED=1ENVPATH/usr/local/bin:$PATH#设置工作目录WORKDIR/home/lab#复制项目文件到容器中COPY./home/lab/#COPYrequirements.txt/home/lab#安装依赖包(先更新pip,换源,再安装包)......
  • 迅为3588开发板Ubuntu安装Docker
      在使用迅为RK3588开发板的时候,我们一般采用的是虚拟机安装Ubuntu20.04来编译Android源码或者linux源码,但是编译源码最让人头疼的是主机环境问题。假如我手上有很多块开发板,每个开发板都使用不同的编译环境,而我本地电脑已经有一个编译环境了,那怎么办呢?  有没......
  • Docker-compose
    DOCKER-COMPOSE简介DockerCompose是一个用于定义和运行多容器Docker应用程序的工具。它允许用户使用YAML文件来定义应用程序的配置,包括容器的数量、容器之间的依赖关系、环境变量、端口映射以及其他设置。然后,用户可以使用docker-compose命令来启动和管理这些容器。使......
  • docker部署(使用docker-compose)手把手教程
    docker部署(使用docker-compose)手把手教程:https://blog.csdn.net/qq_38377190/article/details/125504426?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170650340916800186593495%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=1706......
  • 无涯教程-Swift - 继承
    通常,一个类可以从另一个类继承方法,属性和函数。类可以进一步分类为子类和父类。子类  - 当一个类从另一个类继承属性,方法和函数时,称为子类父类  - 包含从其自身继承其他类的属性,方法和函数的类称为超类Swift4类包含调用和访问方法,属性,函数和覆盖方法的父类,此外,......
  • 无涯教程-Swift - Subscripts(下标)
    Subscripts下标可以访问类,结构和枚举中的集合,序列和列表的元素成员。这些下标用于在索引的帮助下存储和检索值。在someArray[index]的帮助下访问数组元素,而在Dictionary中的后续成员元素可以作为someDicitonary[key]访问。下标声明语法 "subscript"关键字用于定义,用户可以......
  • 【教程】iOS 手机抓包工具介绍及教程
    ......
  • 无涯教程-Swift - Method(方法)
    在Swift4语言中,与特定类型关联的函数称为"方法"。在ObjectiveC中,类用于定义方法,而Swift4语言为用户提供了具有类,结构和枚举方法的灵活性。实例方法在Swift4语言中,可通过方法访问Class,Structures和Enumeration。方法可以写在{}花括号内,它具有对类型的方法和属性的隐式访问,......