当前位置: 首页 > article >正文

docker学习使用教程

一、Docker概述

(一)概述

1.Docker为什么会出现?

业务是基于应用(Application)运转的。曾经,每个服务器只能运行单一应用。每次想要增加一个新的应用时,公司就需要去采购一个新的服务器。

由于没有人知道新增应用所需的服务器性能究竟是怎样的,在采购的时候就不得不买那些性能大幅优于业务需求的服务器。这种做法导致了大部分服务器长期运行在他们额定负载5%~10%的水平区间之内。这对公司资产和资源是一种极大的浪费!

虚拟机

为了解决上面的问题,VMware公司给全世界带来了一个礼物——虚拟机(VM)​。每当需要增加应用的时候,公司无须采购新的服务器。取而代之的是,尝试在现有的,并且有空闲性能的服务器上部署新的应用。

但是虚拟机最大的缺点就是依赖其专用的操作系统(OS)​。OS会占用额外的CPU、RAM和存储,这些资源本可以用于运行更多的应用。每个OS都需要补丁和监控。虚拟机技术也面临着一些其他挑战。比如虚拟机启动通常比较慢,并且可移植性比较差——虚拟机在不同的虚拟机管理器(Hypervisor)或者云平台之间的迁移要远比想象中困难。

容器

长期以来,像谷歌(Google)这样的大规模Web服务(Big Web-Scale)玩家一直采用容器(Container)技术解决虚拟机模型的缺点。

容器模型其实跟虚拟机模型相似,其主要的区别在于,容器的运行不会独占操作系统。实际上,运行在相同宿主机上的容器是共享一个操作系统的,这样就能够节省大量的系统资源,如CPU、RAM以及存储。

容器同时还能节省大量花费在许可证上的开销,以及为OS打补丁等运维成本。最终结果就是,容器节省了维护成本和资金成本。同时容器还具有启动快和便于迁移等优势。

而Docker是一种运行于Linux和Windows上的软件,用于创建、管理和编排容器。

在这里插入图片描述

2.什么是Docker?

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

多数技术人员在谈到Docker时,主要是指Docker引擎。Docker引擎是用于运行和编排容器的基础设施工具。

3.docker是怎么运行的?

在这里插入图片描述
类似于redis,首先运行一个docker的服务端,然后通过docker的客户端进行构建、拉取、运行。

docker会首先在本地仓库寻找镜像运行,若不存在就会去外部Docker仓库查找镜像运行。在外部仓库查找到镜像之后下载到本地进行运行,若依然不存在则会报错。

在这里插入图片描述

镜像(image)

docker镜像好比一个模板,可以通过这个模板来创建容器服务。

容器(container)

docker利用容器技术,独立运行一个或一组应用,通过镜像创建的。

可以把容器简单理解为一个简易版的linux系统,有启动、停止、删除的基本命令。

仓库(repository)

仓库是存放镜像的地方。仓库分为公有仓库和私有仓库。公有的仓库默认是国外的DockerHub,需要配置国内的镜像加速。

(二)Docker安装

docker官方帮助文档:https://docs.docker.com

1.linux版Docker

(1)卸载旧版本

如果已安装这些程序,请卸载它们以及相关的依赖项。

$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
(2)安装必要的软件包

yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。

$ sudo yum install -y yum-utils
(3)设置国内的镜像仓库

官方源的地址仓库比较慢,下面设置国内(阿里云)的镜像仓库。

$ sudo yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(4)安装docker

安装最新版本的 Docker Engine-Community 和 containerd,或者转到下一步安装特定版本:

$ sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
(5)启动docker

安装完成后启动docker。

systemctl start docker

启动完成后,查看版本是否启动成功

docker version

在这里插入图片描述

docker的默认工作路径在/var/lib/docker

(6)测试docker

通过运行 hello-world 镜像来验证是否正确安装了 Docker Engine-Community 。

$ sudo docker run hello-world

显示如下,就说明docker安装运行正常。
在这里插入图片描述

(7)问题解决

有可能运行不正常,可能是没有使用国内镜像导致的。可以多尝试几种国内镜像源。

sudo vi /etc/docker/daemon.json

编辑添加以下的几种镜像源

{
  "registry-mirrors":
    [
      "https://docker.m.daocloud.io/",
      "https://huecker.io/",
      "https://dockerhub.timeweb.cloud",
      "https://noohub.ru/",
      "https://dockerproxy.com",
      "https://docker.mirrors.ustc.edu.cn",
      "https://docker.nju.edu.cn",
      "https://xx4bwyg2.mirror.aliyuncs.com",
      "http://f1361db2.m.daocloud.io",
      "https://registry.docker-cn.com",
      "http://hub-mirror.c.163.com",
      "https://docker.mirrors.ustc.edu.cn"
    ]
}

修改完成后,重启 Docker 服务:

sudo systemctl restart docker

2.windows版Docker

以前Docker只能安装在linux系统上,现在由于微软公司和Docker公司的合作,Docker可以安装在win10及以上的版本的操作系统上。

Docker Desktop 是 Docker 在 Windows 10 和 macOS 操作系统上的官方安装方式,这个方法依然属于先在虚拟机中安装 Linux 然后再安装 Docker 的方法。

Docker Desktop 官方下载地址: https://docs.docker.com/desktop/install/windows-install/

在这里插入图片描述

注意:此方法仅适用于 Windows 10 操作系统专业版、企业版、教育版和部分家庭版!

(1)开启 Hyper-V

在安装之前,Windows版Docker的环境需要确认在Windows 10操作系统中,Hyper-V和容器特性已安装并且开启。

Hyper-V 是微软开发的虚拟机,类似于 VMWare 或 VirtualBox,仅适用于 Windows 10。这是 Docker Desktop for Windows 所使用的虚拟机。

但是,这个虚拟机一旦启用,QEMU、VirtualBox 或 VMWare Workstation 15 及以下版本将无法使用!如果你必须在电脑上使用其他虚拟机(例如开发 Android 应用必须使用的模拟器),请不要使用 Hyper-V!

在这里插入图片描述
如图,在“控制面板-程序和功能-启用或关闭Windows功能”中确认Hyper-V和容器复选框已经被勾选,并单击确定按钮。

(2)安装 Docker Desktop for Windows

下载 Windows 的版本,如果你还没有登录,会要求注册登录:

Docker默认的安装路径是在C:\Program Files\Docker\Docker,可按下列命令指定安装的路径:

"Docker Desktop Installer.exe"  install --installation-dir="D:\Program Files\Docker"

提前已经在windows系统中配置好了虚拟linux环境,配置WSL或启用Hyper-V二选一。
在这里插入图片描述

推荐使用windows子系统WSL,它需要占用系统盘30G的空间。(需要确保C盘有30G的空间,否则安装失败)

(3)启动docker

在这里插入图片描述
可能会报错
在这里插入图片描述

wsl --update

在这里插入图片描述

二、docker基本使用

(一)基本命令

1.帮助命令

若不知道docker有哪些命令,或者怎么使用,可以输入以下命令进行查询:

docker --help

在这里插入图片描述

各命令官方文档:https://docs.docker.com/reference/cli/docker/

2.查看docker详细信息

查看docker详细信息,包括镜像、容器数量

docker info

在这里插入图片描述

(二)镜像命令

1.查看docker镜像

docker images

在这里插入图片描述

2.搜索docker镜像

docker search  镜像名

由于docker默认搜索国外镜像源,而国内镜像源只支持加快拉取,因此搜索功能的生效需要翻墙才行。

或者在国内主流镜像服务(如阿里云、腾讯云、网易云等)提供的网页界面搜索镜像。

阿里云官方镜像站:https://developer.aliyun.com/mirror/

3.拉取docker镜像

拉取镜像就是从中央仓库下载镜像到本地。

docker pull 镜像名[:tag]

如果不声明tag镜像标签信息则默认拉取latest版本。

在这里插入图片描述

4.删除docker镜像

(1)删除单个镜像

可以按镜像名+版本号删除某个镜像

docker rmi -f 镜像名

也可以按镜像ID删除单个镜像。

docker rmi 镜像ID

在这里插入图片描述

(2)删除多个镜像

按镜像ID删除多个镜像。

执行命令:

docker rmi 镜像ID 镜像ID 镜像ID
(3)删除所有镜像

docker images -q可以查询到所有镜像的ID,通过组合命令可以实现删除所有镜像的操作。

执行命令:

docker rmi docker images -q

(三)容器命令

1.查看运行中的容器

查看正在运行的容器。

docker ps 
# 参数说明
     # 列出最近正在运行的容器
-a   # 列出所有运行过的容器,带出历史中运行的容器
-n=? # 列出最近几项运行过高的容器
-q   # 显示容器编号

在这里插入图片描述
在这里插入图片描述

(1)查看停止的容器。

执行命令:

docker ps -f status=exited
(2)查看所有容器(包括运行和停止)。

执行命令:

docker ps -a
(3)查看最后一次运行的容器。

执行命令:

docker ps -l
(4)列出最近创建的 n 个容器。
执行命令:docker ps -n 5

2.创建并运行容器

Docker用Registry来保存用户构建的镜像。Registry分为公共和私有两种。Docker公司运营公共的Registry叫做Docker Hub。用户可以在Docker Hub注册账号,分享并保存自己的镜像。

Docker公司提供了公共的镜像仓库https://hub.docker.com(Docker 称之为 Repository)提供了庞大的镜像集合供使用。

一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签对应该软件的各个版本。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。

在这里插入图片描述
下面为docker创建并运行容器的命令

docker run [可选参数] image
# 参数说明

-i 表示运行容器;
-t 表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端
--name 为创建的容器命名,例如tomcat1,tomcat2,用来区分容器
-v 表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个 -v 做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上;
-d 在 run 后面加上 -d 参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加 -i -t 两个参数,创建容器后就会自动进容器里);
-p 表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射。
-P 随机使用宿主机的可用端口与容器内暴露的端口映射。
(1)创建并进入容器

下面这行命令的意思就是通过镜像 AA 创建一个容器 BB,运行容器并进入容器的/bin/bash。

docker run -it --name 容器名称 镜像名称:标签 /bin/bash

注意:Docker容器运行必须有一个前台进程,如果没有前台进程执行,容器认为是空闲状态,就会自动退出。

(2)守护式方式创建容器

创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加 -i -t 两个参数,创建容器后就会自动进容器里)

docker run -di --name 容器名称 镜像名称:标签
(3)登录守护式容器方式

在指定的运行中Docker容器内启动一个新的交互式Bash shell会话,允许用户直接在容器内部执行命令和操作文件系统等任务。这对于调试、检查容器内部状态或者进行实时修改都非常有用。

docker exec -it 容器名称|容器ID /bin/bash

请注意,这条命令不会创建一个新的容器,而是作用于已经存在的且正在运行的容器上。如果你尝试对未运行的容器使用这个命令,将会失败。

(4)退出容器

进入容器内部后,按以下方式退出

exit      # 停止容器并退出
Ctrl+p+q  # 容器不停止的退出

3.删除容器

(1)删除单个容器

删除一个或多个已经停止运行的Docker容器。你可以通过容器的ID或者名称来指定要删除的容器。

docker rm 容器名称|容器ID  

默认情况下,你不能使用这个命令删除正在运行的容器。

如果尝试删除正在运行的容器,将会收到错误信息。然而,如果你确实需要删除正在运行的容器,可以添加 -f 或 --force 参数来强制删除。

注意:删除镜像命令是docker rmi,需要仔细区分。

(2)删除所有容器

这条命令组合使用了两个Docker命令来删除所有容器(包括正在运行和已停止的)。

docker rm -f $(docker ps -aq) # 删除所有的容器

请确保你在执行这条命令之前确实希望删除所有容器,因为这将不可逆地移除所有容器及其数据,除非这些数据被挂载到了主机系统的卷中。

4.停止和启动容器

(1)停止容器

停止一个或多个正在运行中的Docker容器。可以通过容器的名称或者容器ID来指定要停止的容器。

docker stop 容器名称|容器ID

这种方式允许应用程序有机会正确地处理关闭前的操作,比如保存状态、关闭数据库连接等。

(2)启动容器

该命令命令是用来启动一个已经存在但是当前处于停止状态的Docker容器。

docker start 容器名称|容器ID

当你使用docker start命令时,Docker会重新启动指定的容器,并且以之前创建容器时定义的方式运行它,包括使用相同的参数和选项。

如果容器之前被正确地停止(即不是通过docker rm命令删除),那么它的文件系统、挂载的数据卷以及其他配置都会保持原样,容器将从上次停止的地方继续运行。

(3)重启容器

重启一个或多个Docker容器。你可以通过容器的ID或者名称来指定要重启的容器。

docker restart 容器名称|容器ID

实际上,docker restart命令相当于依次执行docker stopdocker start命令。首先它会尝试优雅地停止指定的容器,然后再次启动该容器。

这对于需要重新加载配置或应用更新而不必完全删除和重新创建容器的情况非常有用。

(4)强制停止容器

强制停止容器的运行。

它直接向容器内的主进程发送SIGKILL信号以立即终止容器,而不是给容器内进程机会去优雅地处理关闭流程。

docker kill 容器名称|容器ID

这个命令通常只在必要时使用,比如当容器无响应或出现异常行为时。

5.文件拷贝

有时候我们想在主机与Docker容器之间进行文件传输,但又不想先登录到容器内部再手动拷贝文件,docker cp 命令可以帮助我们解决问题。

(1)容器外拷贝到容器内

如果我们需要将文件拷贝到容器内可以使用cp命令。

docker cp 需要拷贝的文件或目录 容器名称:容器目录

例如,如果你想将主机上的 /home/user/data.txt 文件拷贝到名为 my_container 的容器内的 /app/data/ 目录下,可以使用如下命令:

docker cp /home/user/data.txt my_container:/app/data/
(2)容器内拷贝到容器外

也可以将文件从容器内拷贝出来。

docker cp 容器名称:容器目录 需要拷贝的文件或目录

例如,如果想把名为 my_container 的容器内的 /app/data/report.txt 文件拷贝到主机的 /home/user/reports/ 目录下,你可以执行以下命令:

docker cp my_container:/app/data/report.txt /home/user/reports/

6.目录挂载

实际上我们的容器就好像是一个简易版的操作系统,只不过系统中只安装了我们的程序运行所需要的环境,前边说到我们的容器是可以删除的,那如果删除了,容器中的程序产生的需要持久化的数据怎么办呢?容器运行的时候我们可以进容器去查看,容器一旦删除就什么都没有了。

所以数据卷就是来解决这个问题的,是用来将数据持久化到我们宿主机上,与容器间实现数据共享,简单的说就是将宿主机的目录映射到容器中的目录,应用程序在容器中的目录读写数据会同步到宿主机上,这样容器产生的数据就可以持久化了,比如我们的数据库容器,就可以把数据存储到我们宿主机上的真实磁盘中。

我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器,而且这个操作是双向绑定的,也就是说容器内的操作也会影响到宿主机,实现备份功能。

但是容器被删除的时候,宿主机的内容并不会被删除。如果多个容器挂载同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

Docker中的目录挂载通常通过使用-v--mount选项来实现,这允许你将主机的文件系统中的一个目录(或单个文件)挂载到容器内的指定位置。

命令格式如下:

# 单目录挂载
docker run -v /宿主机路径:/容器内路径[:选项] 镜像名
# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名

这种机制对于共享数据、持久化存储容器内生成的数据或者在开发过程中实时更新代码特别有用。

例如:

docker run -di -v /home/project/data:/usr/local/data --name centos7-01 centos:7

注意:当挂载一个目录时,如果容器内对应路径已存在内容,那么这些内容会被挂载的主机目录内容所掩盖。

(1)匿名挂载

匿名挂载只需要写容器目录即可,容器外对应的目录会在/var/lib/docker/volumes中生成。

# 匿名挂载
docker run -di -v /usr/local/data --name centos7-02 centos:7
# 查看 volume 数据卷信息
docker volume ls
(2)具名挂载

具名挂载就是给数据卷起了个名字,容器外对应的目录会在/var/lib/docker/volume中生成。

# 具名挂载
docker run -di -v docker_centos_data:/usr/local/data --name centos7-03 centos:7
# 查看 volume 数据卷信息
docker volume ls
(3)指定目录挂载

之前挂载方式就属于指定目录挂载,这种方式的挂载不会在/var/lib/docker/volume目录生成内容。

docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名
(4)只读/读写
# 只读。只能通过修改宿主机内容实现对容器的数据管理。
docker run -it -v /宿主机目录:/容器目录:ro 镜像名

# 读写,默认。宿主机和容器可以双向操作数据。
docker run -it -v /宿主机目录:/容器目录:rw 镜像名

这里,:ro 可以作为选项添加在后面来使挂载点为只读(read-only),例如:

docker run -v /project:/app:ro my_image
(5)挂载的新语法

使用 --mount 选项,提供了更清晰和更强大的配置方式,适用于更复杂的场景:

docker run --mount type=bind,source=/宿主机路径,target=/容器内路径[,readonly] 镜像名

例如,使用 --mount 来挂载 /project/app,设置挂载点为只读,可以这样操作:

docker run --mount type=bind,source=/project,target=/app,readonly my_image
(6)查看目录挂载关系

通过docker volume inspect数据卷名称 可以查看该数据卷对应宿主机的目录地址。

执行命令:

docker volume inspect docker_centos_data

通过docker inspect容器ID或名称 ,在返回的JSON节点中找到Mounts,可以查看详细的数据挂载信息。

(四)常用其它命令

1.显示日志

docker logs
# 参数
-tf          # 显示日志
-tail number # 指定日志条数

2.查看容器进程

docker top 

在这里插入图片描述

3.查看元数据

docker inspect 

在这里插入图片描述

4.进入正在运行的容器

docker exec -it 容器id  # 进入之后开启一个新的终端
docker attach 容器id    # 进入正在执行的终端,不会开启新进程

5.从容器内拷贝文件到主机

docker cp  容器id:容器内路径   主机路径

如图,进入容器内,在容器里创建一个文件后,退出容器,然后拷贝文件到当前主机。
在这里插入图片描述

三、应用部署实例

(一)部署Nacos

拉取官方nacos镜像

执行命令:

docker pull nacos/nacos-server

启动nacos

docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server

启动成功后,可以访问http://目标IP:8848/nacos/index.html访问网页了。

(二)Nginx

拉取官方nginx镜像

执行命令:

docker pull nginx

创建Nginx容器。

docker run -di --name nginx -p 80:80 nginx

将容器内的配置文件拷贝到指定目录(请先提前创建好目录)。

# 创建目录
mkdir -p /data/nginx

# 将容器内的配置文件拷贝到指定目录
docker cp nginx:/etc/nginx /data/nginx/conf

终止并删除容器

docker stop nginx
docker rm nginx

创建Nginx容器,并将容器中的/etc/nginx目录和宿主机的/data/nginx/conf目录进行挂载。

docker run -di --name nginx -p 80:80 -v /data/nginx/conf:/etc/nginx nginx

(三)Mysql

拉取官方mysql5.7镜像

执行命令:

docker pull mysql:5.7

在本地创建mysql的映射目录

mkdir -p /home/mysql/data /home/mysql/logs /home/mysql/conf

创建容器,将数据、日志、配置文件映射到本机

docker run -p 3306:3306 --name mysql -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/logs:/logs -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7

进入容器/执行命令:

docker exec -it mysql /bin/bash

(四)Redis

拉取官方redis镜像,执行命令:

docker pull redis

创建容器。

docker run -di --name redis -p 6379:6379 redis

连接容器中的Redis时,只需要连接宿主机的IP + 指定的映射端口即可。

四、镜像构建

我们可以通过公共仓库拉取镜像使用,但是,有些时候公共仓库拉取的镜像并不符合我们的需求。尽管已经从繁琐的部署工作中解放出来,但是实际开发时,我们可能希望镜像包含整个项目的完整环境,在其他机器上拉取打包完整的镜像,直接运行即可。

Docker 支持自己构建镜像,还支持将自己构建的镜像上传至公共仓库,镜像构建可以通过以下两种方式来实现:

  • docker commit:从容器创建一个新的镜像;
  • docker build: 配合Dockerfile文件创建镜像。

(一)从容器创建新的镜像

下面我们先通过docker commit来实现镜像的构建。

目标:接下来我们通过基础镜像centos:7,在该镜像中安装jdk和tomcat以后将其制作为一个新的镜像mycentos:7

1.创建容器

# 拉取镜像
docker pull centos:7

# 创建容器
docker run -di --name centos7 centos:7

2. 拷贝资源和安装资源

例如,将jdk和tomcat安装配置至容器中

# 将宿主机的 jdk  拷贝至容器
docker cp jdk-8u111-linux-x64.tar.gz centos7:/root

# 将宿主机的tomcat 拷贝至容器
docker cp apache-tomcat-8.5.27.tar.gz centos7:/root

安装java和tomcat软件并配置环境

# 进入容器
docker exec -it centos7 /bin/bash

# 切换至 /root 目录
cd root/

# 创建 java 和 tomcat 目录
mkdir -p /usr/local/java
mkdir -p /usr/local/tomcat

# 将 jdk 和 tomcat 解压至容器 /usr/local/java 和 /usr/local/tomcat 目录中
tar -zxvf jdk-8u111-linux-x64.tar.gz -C /usr/local/java/
tar -zxvf apache-tomcat-8.5.27.tar.gz -C /usr/local/tomcat/

# 配置 jdk 环境变量
vi /etc/profile

# 在环境变量文件中添加以下内容
export JAVA_HOME=/usr/local/java/jdk1.8.0_111/
export PATH=$PATH:$JAVA_HOME/bin

# 重新加载环境变量文件
source /etc/profile

# 测试环境变量是否配置成功
java -version

# 删除容器内 jdk 和 tomcat
rm jdk-8u111-linux-x64.tar.gz apache-tomcat-8.5.27.tar.gz -rf

3.构建镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
docker commit -a="author_name" -m="jdk8 and tomcat8" centos7 mycentos:7

-a:提交的镜像作者;
-c:使用 Dockerfile 指令来创建镜像;
-m:提交时的说明文字;
-p:在 commit 时,将容器暂停。

4.使用构建的镜像创建容器

# 创建容器
docker run -di --name mycentos7 -p 8080:8080 mycentos:7

# 进入容器
docker exec -it mycentos7 /bin/bash

# 重新加载配置文件
source /etc/profile

# 测试 java 环境变量
java -version

# 启动 tomcat
/usr/local/tomcat/apache-tomcat-8.5.27/bin/startup.sh

访问http://{ip}:{port},看到tomcat页面说明环境表示成功。

(二)配合Dockerfile文件创建镜像

在Docker中构建镜像最常用的方式,就是使用DockerfileDockerfile是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

官方文档:https://docs.docker.com/engine/reference/builder

1.Dockerfile 常用指令

指令语法说明
FROMFROM :指明构建的新镜像是来自于哪个基础镜像,如果没有选择 tag ,那么默认值为 latest
MAINTAINERMAINTAINER 指明镜像维护者及其联系方式(一般是邮箱地址)。官方说明已过时,推荐使用 LABEL
LABELLABEL = …功能是为镜像指定标签。也可以使用 LABEL 来指定镜像作者
RUNRUN 构建镜像时运行的 shell 命令,比如构建的新镜像中我们想在 /usr/local 目录下创建一个 java 目录
ADDADD … 拷贝文件或目录到镜像中。src 可以是一个本地文件,还可以是一个 url 。然后自动下载和解压
COPYCOPY … 拷贝文件或目录到镜像中。用法同 ADD,只是不支持自动下载和解压
EXPOSEEXPOSE [port]/[protocol]…暴露容器运行时的监听端口给外部。可以指定端口是监听 TCP 还是 UDP,如果未指定协议,则默认为 TCP
ENVENV = …设置容器内环境变量
CMDCMD [“executable”,“param1”,“param2”]启动容器时执行的 Shell 命令,在 Dockerfile 中只能有一条 CMD 指令。如果设置了多条 CMD ,只有最后一条会生效
ENTRYPOINTENTRYPOINT [“executable”, “param1”, “param2”]启动容器时执行的 Shell 命令,同 CMD 类似,不会被 docker run 命令行指定的参数所覆盖,如果设置了多条 ENTRYPOINT ,只有最后一条会生效
WORKDIRWORKDIR param为 RUN、CMD、ENTRYPOINT 以及 COPY 和 AND 设置工作目录
VOLUMEVOLUME [“param”]指定容器挂载点到宿主机自动生成的目录或其他容器。一般的使用场景为需要持久化存储数据时

2.构建镜像

Dockerfile文件编写好以后,真正构建镜像时需要通过docker build命令。

docker build命令用于使用Dockerfile创建镜像。

# 使用当前目录的 Dockerfile 创建镜像
docker build -t mycentos:7 .

# 通过 -f Dockerfile 文件的位置创建镜像
docker build -f /home/ruoyi/docker/Dockerfile -t mycentos:7 .

-f:指定要使用的 Dockerfile 路径;
–tag, -t:镜像的名字及标签,可以在一次构建中为一个镜像设置多个标签。

3.Dockerfile 实践

接下来我们通过基础镜像centos:7,在该镜像中安装jdk和tomcat以后将其制作为一个新的镜像mycentos:7

(1)编写Dockerfile文件

创建目录,编写Dockerfile文件

mkdir -p /usr/local/`dockerfile`

执行命令:vi Dockerfile,写入信息。

# 指明构建的新镜像是来自于`centos:7`基础镜像
FROM centos:7
# 通过镜像标签声明了作者信息
LABEL maintainer="ruoyi.vip"

# 设置工作目录
WORKDIR /usr/local
# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
# 拷贝文件到镜像中并解压
ADD jdk-8u111-linux-x64.tar.gz /usr/local/java
ADD apache-tomcat-8.5.27.tar.gz /usr/local/tomcat
# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080
# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_111
ENV PATH $PATH:$JAVA_HOME/bin
# 启动容器时启动 tomcat
CMD ["/usr/local/tomcat/apache-tomcat-8.5.27/bin/catalina.sh", "run"]
(2)构建镜像
docker build -f /home/ruoyi/docker/Dockerfile -t mycentos:test .
(3)启动镜像
docker run -di --name mycentos -p 8080:8080 mycentos:test
(4)进入容器
docker exec -it mycentos7 /bin/bash

五、定义运行多容器(Docker Compose)

我们可以通过Dockerfile文件让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况,或者开发一个Web应用,除了Web服务容器本身,还需要数据库服务容器、缓存容器,甚至还包括负载均衡容器等等。

Docker Compose恰好满足了这样的需求,它是用于定义和运行多容器Docker应用程序的工具。通过Compose,您可以使用YAML文件来配置应用程序所需要的服务。然后使用一个命令,就可以通过YAML配置文件创建并启动所有服务。

Docker Compose项目是Docker官方的开源项目,来源于之前的Fig项目,使用Python语言编写。负责实现对Docker容器集群的快速编排。

项目地址为:https://github.com/docker/compose/releases

Docker Compose使用的三个步骤为:

  • 使用Dockerfile文件定义应用程序的环境;
  • 使用docker-compose.yml文件定义构成应用程序的服务,这样它们可以在隔离环境中一起运行;
  • 执行docker-compose up命令来创建并启动所有服务。

(一)Compose 安装

官方文档:https://docs.docker.com/compose/install/

可以在macOS,Windows和Linux上运行Compose。本文演示基于Linux环境的安装。我们可以使用curl命令从Github下载它的二进制文件来使用,运行以下命令下载Docker Compose的当前稳定版本。

或者从网页下载后上传至服务器指定目录/usr/local/bin也行。

1.下载

# 从github下载
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 因为Docker Compose存放在GitHub,可能不太稳定。可以通过DaoCloud加速下载
curl -L https://get.daocloud.io/docker/compose/releases/download/1.26.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

可以通过修改 URL 中的版本,自定义您所需要的版本文件。

安装完成以后,查看指定目录,发现该文件没有可执行权限,进行授权操作。

2.授权

# 将可执行权限应用于该二进制文件
sudo chmod +x /usr/local/bin/docker-compose

3.测试

docker-compose --version

4.删除

rm /usr/local/bin/docker-compose

(二)docker-compose.yml 文件详解

官方文档:https://docs.docker.com/compose/compose-file/

Docker Compose允许用户通过docker-compose.yml文件(YAML 格式)来定义一组相关联的容器为一个工程(project)。一个工程包含多个服务(service),每个服务中定义了创建容器时所需的镜像、参数、依赖等。

Docker Compose模板文件我们需要关注的顶级配置有version、services、networks、volumes几个部分,除version外,其他几个顶级配置下还有很多下级配置,后面也会详细给大家介绍,先来看看这几个顶级配置都什么意思:

  • version:描述Compose文件的版本信息,当前最新版本为3.8,对应的Docker版本为19.03.0+
  • services:定义服务,可以多个,每个服务中定义了创建容器时所需的镜像、参数、依赖等
  • networkds:定义网络,可以多个,根据DNS server让相同网络中的容器可以直接通过容器名称进行通信
  • volumes:数据卷,用于实现目录挂载

1.使用示例

# 描述 Compose 文件的版本信息
version: "3.8"

# 定义服务,可以多个
services:
  nginx: # 服务名称
    image: nginx # 创建容器时所需的镜像
    container_name: mynginx # 容器名称,默认为"工程名称_服务条目名称_序号"
    ports: # 宿主机与容器的端口映射关系
      - "80:80" # 左边宿主机端口:右边容器端口
    networks: # 配置容器连接的网络,引用顶级 networks 下的条目
      - nginx-net

# 定义网络,可以多个。如果不声明,默认会创建一个网络名称为"工程名称_default"的 bridge 网络
networks:
  nginx-net: # 一个具体网络的条目名称
    name: nginx-net # 网络名称,默认为"工程名称_网络条目名称"
    driver: bridge # 网络模式,默认为 bridge

使用docker-compose up创建并启动所有服务。

# 前台启动
docker-compose up

# 后台启动
docker-compose up -d

使用docker-compose down可以停止并删除容器、网络。

2.version 版本信息

描述Compose文件的版本信息,当前最新版本为3.8,对应的Docker版本为19.03.0+。

关于每个版本的详细信息请参考:https://docs.docker.com/compose/compose-file/compose-versioning/

以下为Compose文件的版本信息所对应的Docker版本。

Compose file formatDocker Engine release
3.819.03.0+
3.718.06.0+
3.618.02.0+
3.517.12.0+
3.417.09.0+
3.317.06.0+
3.217.04.0+
3.11.13.1+
3.01.13.0+
1.xx

2.services 定义服务

services用来定义服务,可以多个,每个服务中定义了创建容器时所需的镜像、参数、依赖等,就像将命令行参数传递给docker run一样。同样,网络和数据卷的定义也是一样的。

比如,通过docker run命令构建一个MySQL应用容器的命令如下:

docker run -di --name mysql8 -p 3306:3306 -v /mydata/docker_mysql/conf:/etc/mysql/conf.d -v /mydata/docker_mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=1234 mysql:8

使用docker-compose.yml以后则可以这样定义:

version: "3.8"
# 定义服务,可以多个
services:
  mysql: # 服务名称
    image: mysql:8 # 创建容器时所需的镜像
    container_name: mysql8 # 容器名称,默认为"工程名称_服务条目名称_序号"
    ports: # 宿主机与容器的端口映射关系
      - "3306:3306" # 左边宿主机端口:右边容器端口
    environment: # 创建容器时所需的环境变量
      MYSQL_ROOT_PASSWORD: 1234
    volumes:
      - "/mydata/docker_mysql/conf:/etc/mysql/conf.d"
      - "/mydata/docker_mysql/data:/var/lib/mysql"

3.image 镜像名称标签

指定创建容器时所需的镜像名称标签或者镜像ID。如果镜像在本地不存在,会去远程拉取。

services:
  web:
    image: hello-world

4.build 构建容器和context 文件路径

除了可以基于指定的镜像构建容器,还可以基于Dockerfile文件构建,在使用up命令时会执行构建任务。

该选项可以是Dockerfile文件的绝对/相对路径,也可以是远程Git仓库的URL,当提供的值是相对路径时,相对当前docker-compose.yml文件所在目录。

build:
  context: . # 相对当前 docker-compose.yml 文件所在目录,基于名称为 Dockerfile 的文件构建镜像

5.dockerfile 构建镜像

一般情况下,默认都基于文件名叫Dockerfile的文件构建镜像,当然也可以是自定义的文件名,使用dockerfile声明,不过这个选项只能声明文件名,文件所在路径还是要通过centext来声明。

build:
  context: . # 相对当前 docker-compose.yml 文件所在目录
  dockerfile: Dockerfile-alternate # 基于名称为 Dockerfile-alternate 的文件构建镜像

6.container_name 容器名称

Compose创建的容器默认生成的名称格式为:工程名称_服务条目名称_序号。如果要使用自定义名称,使用container_name声明。

services:
  mycentos:
    build: .
    container_name: mycentos7 # 容器名称,默认为"工程名称_服务条目名称_序号"

因为Docker容器名称必须是唯一的,所以如果指定了自定义名称,就不能将服务扩展至多个容器。这样做可能会导致错误。

7.depends_on 容器依赖

使用Compose最大的好处就是敲最少的命令做更多的事情,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。

例如在没有启动数据库容器的情况下启动了Web应用容器,应用容器会因为找不到数据库而退出。depends_on就是用来解决容器依赖、启动先后问题的配置项。

version: "3.8"

services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: mysql

上述YAML文件定义的容器会先启动db和redis两个服务,最后才启动web服务。

8.ports 暴露端口

容器对外暴露的端口,格式:左边宿主机端口:右边容器端口。

ports:
  - "80:80"
  - "8080:8080"

9.expose 接受端口范围

容器暴露的端口不映射到宿主机,只允许能被连接的服务访问。

expose:
  - "80"
  - "8080"

10.restart 重启策略

容器重启策略,简单的理解就是Docker重启以后容器要不要一起启动

  • no:默认的重启策略,在任何情况下都不会重启容器;
  • on-failure:容器非正常退出时,比如退出状态为非0(异常退出),才会重启容器;
  • always:容器总是重新启动,即使容器被手动停止了,当Docker重启时容器也还是会一起启动;
  • unless-stopped:容器总是重新启动,除非容器被停止(手动或其他方式),那么Docker重启时容器则不会启动。
services:
  nginx:
    image: nginx
    container_name: mynginx
    ports:
      - "80:80"
    restart: always

11.environment 环境变量

添加环境变量。可以使用数组也可以使用字典。布尔相关的值(true、false、yes、no)都需要用引号括起来,以确保 YML 解析器不会将它们转换为真或假。

environment:
  RUOYI_ENV: development
  SHOW: 'true'
  SESSION_SECRET:

或者以下格式:

environment:
  - RUOYI_ENV=development
  - SHOW=true
  - SESSION_SECRET

env_file 文件获取环境变量
从文件中获取环境变量,可以指定一个或多个文件,其优先级低于environment指定的环境变量。

env_file:
  - /opt/runtime_opts.env # 绝对路径
  - ./common.env # 相对路径,相对当前 docker-compose.yml 文件所在目录
  - ./apps/web.env # 相对路径,相对当前 docker-compose.yml 文件所在目录

注意:env 文件中的每一行需采用键=值格式。以#开头的行会被视为注释并被忽略。空行也会被忽略。

12.command 执行命令

覆盖容器启动后默认执行的命令。

command: echo "helloworld"

该命令也可以是一个列表。

command: ["echo", "helloworld"]

13.volumes 目录挂载

数据卷,用于实现目录挂载,支持指定目录挂载、匿名挂载、具名挂载。

  • 指定目录挂载的格式为:左边宿主机目录:右边容器目录,或者左边宿主机目录:右边容器目录:读写权限;
  • 匿名挂载格式为:容器目录即可,或者容器目录即可:读写权限;
  • 具名挂载格式为:数据卷条目名称:容器目录,或者数据卷条目名称:容器目录:读写权限。
# 描述 Compose 文件的版本信息
version: "3.8"

# 定义服务,可以多个
services:
  mysql: # 服务名称
    image: mysql:8 # 创建容器时所需的镜像
    container_name: mysql8 # 容器名称,默认为"工程名称_服务条目名称_序号"
    ports: # 宿主机与容器的端口映射关系
      - "3306:3306" # 左边宿主机端口:右边容器端口
    environment: # 创建容器时所需的环境变量
      MYSQL_ROOT_PASSWORD: 1234
    volumes:
      # 绝对路径
      - "/mydata/docker_mysql/data:/var/lib/mysql"
      # 相对路径,相对当前 docker-compose.yml 文件所在目录
      - “./conf:/etc/mysql/conf.d“
      # 匿名挂载,匿名挂载只需要写容器目录即可,容器外对应的目录会在 /var/lib/docker/volume 中生成
      - "/var/lib/mysql"
      # 具名挂载,就是给数据卷起了个名字,容器外对应的目录会在 /var/lib/docker/volume 中生成
      - "mysql-data-volume:/var/lib/mysql"

# 定义数据卷,可以多个
volumes:
  mysql-data-volume: # 一个具体数据卷的条目名称
    name: mysql-data-volume # 数据卷名称,默认为"工程名称_数据卷条目名称"

14.network_mode 网络模式

设置网络模式,类似 docker run 时添加的参数 --net host 或者 --network host 的用法

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

15.networks

配置容器连接的网络,引用顶级 networks 下的条目。

# 定义服务,可以多个
services:
  nginx: # 服务名称
    networks: # 配置容器连接的网络,引用顶级 networks 下的条目
      - nginx-net # 一个具体网络的条目名称

# 定义网络,可以多个。如果不声明,默认会创建一个网络名称为"工程名称_default"的 bridge 网络
networks:
  nginx-net: # 一个具体网络的条目名称
    name: nginx-net # 网络名称,默认为"工程名称_网络条目名称"
    driver: bridge # 网络模式,默认为 bridge

16.aliases

网络上此服务的别名。同一网络上的其他容器可以使用服务名或此别名连接到服务容器。同一服务在不同的网络上可以具有不同的别名。

# 定义服务,可以多个
services:
  nginx: # 服务名称
    networks: # 配置容器连接的网络,引用顶级 networks 下的条目
      nginx-net: # 一个具体网络的条目名称
        aliases: # 服务别名,可以多个
          - nginx1 # 同一网络上的其他容器可以使用服务名或此别名连接到服务容器

# 定义网络,可以多个。如果不声明,默认会创建一个网络名称为"工程名称_default"的 bridge 网络
networks:
  nginx-net: # 一个具体网络的条目名称
    name: nginx-net # 网络名称,默认为"工程名称_网络条目名称"
    driver: bridge # 网络模式,默认为 bridge

(三)项目部署示例

以ruoyi-cloud项目为例,该项目提供了docker部署,只需要复制jar文件到对应的/docker/ruoyi目录下。

docker
├── mysql            // 数据库
│       └── db                            // 数据库脚本
│       └── dockerfile                    // mysql dockerfile
├── nacos            // 注册中心/配置中心
│       └── conf                          // nacos 配置文件
│       └── dockerfile                    // nacos dockerfile
├── nginx            // web服务器
│       └── conf                          // nginx 配置文件
│       └── html                          // 打包后的前端ui
│       └── dockerfile                    // nginx dockerfile
├── redis            // 缓存服务
│       └── conf                          // redis 配置文件
│       └── dockerfile                    // redis dockerfile
├── ruoyi            // 业务模块
│       └── auth                          // 认证中心 dockerfile jar
│       └── gateway                       // 网关模块 dockerfile jar
│       └── modules                       // 业务模块 dockerfile jar
│       └── visual                        // 图形化管理模块 dockerfile jar
├── deploy.sh               // 部署脚本
├── docker-compose.yml      // docker-compose

上传文件到自己的服务器,通过deploy.sh执行命令控制。

# 开启所需端口
./deploy.sh port

# 启动基础环境(必须)
./deploy.sh base

# 启动程序模块(必须)
./deploy.sh modules

# 关闭所有环境/模块
./deploy.sh stop

# 删除所有环境/模块
./deploy.sh rm

deploy.sh文件内容如下:

#!/bin/sh

# 使用说明,用来提示输入参数
usage() {
	echo "Usage: sh 执行脚本.sh [port|base|modules|stop|rm]"
	exit 1
}

# 开启所需端口
port(){
	firewall-cmd --add-port=80/tcp --permanent
	firewall-cmd --add-port=8080/tcp --permanent
	firewall-cmd --add-port=8848/tcp --permanent
	firewall-cmd --add-port=9848/tcp --permanent
	firewall-cmd --add-port=9849/tcp --permanent
	firewall-cmd --add-port=6379/tcp --permanent
	firewall-cmd --add-port=3306/tcp --permanent
	firewall-cmd --add-port=9100/tcp --permanent
	firewall-cmd --add-port=9200/tcp --permanent
	firewall-cmd --add-port=9201/tcp --permanent
	firewall-cmd --add-port=9202/tcp --permanent
	firewall-cmd --add-port=9203/tcp --permanent
	firewall-cmd --add-port=9300/tcp --permanent
	service firewalld restart
}

# 启动基础环境(必须)
base(){
	docker-compose up -d ruoyi-mysql ruoyi-redis ruoyi-nacos
}

# 启动程序模块(必须)
modules(){
	docker-compose up -d ruoyi-nginx ruoyi-gateway ruoyi-auth ruoyi-modules-system
}

# 关闭所有环境/模块
stop(){
	docker-compose stop
}

# 删除所有环境/模块
rm(){
	docker-compose rm
}

# 根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"port")
	port
;;
"base")
	base
;;
"modules")
	modules
;;
"stop")
	stop
;;
"rm")
	rm
;;
*)
	usage
;;
esac


http://www.kler.cn/a/580625.html

相关文章:

  • 航空发动机叶片检测-三维扫描技术重构精密制造质量体系
  • MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)
  • 游戏行业研究系列报告
  • k8s面试题总结(十二)
  • 在mac中设置环境变量
  • 【AIGC系列】6:HunyuanVideo视频生成模型部署和代码分析
  • STM32 CAN模块原理与应用详解
  • MySQL 数据库常用命令
  • postgreSQL window function高级用法
  • Facebook 隐私保护技术的发展与未来趋势
  • 探索在生成扩散模型中基于RAG增强生成的实现与未来
  • 初次体验Tauri和Sycamore(3)通道实现
  • 自然语言处理:无监督朴素贝叶斯模型
  • <3D建模>.max文件转换为.fbx文件
  • Ubuntu 24.04.2 允许 root 登录桌面、 ssh 远程、允许 Ubuntu 客户机与主机拖拽传递文件
  • MyBatis SqlSession 的作用,以及如何使用 SqlSession 执行 SQL 语句
  • Compose 实践与探索一 —— 关键知识与概念详解
  • 应急响应--流量分析
  • anolis8.9-k8s1.32-node-二进制部署
  • SSE vs WebSocket:AI 驱动的实时通信抉择