Docker |
您所在的位置:网站首页 › 虚拟机监控器简称什么 › Docker |
Docker 在前端开发中的应用实例 1、使用 Docker 搭建 WordPress 2、Docker + Nginx 部署 React 应用 3、Docker 部署 node 服务 一、Docker 是什么?了解 Docker 之前,我们先来了解一下虚拟机(Virtual Machine,简称 VM)。 1、什么是虚拟机?「为什么要用虚拟机?」 整合资源是使用虚拟机的首要原因和目的。大多数的操作系统和应用,在安装(部署)时,都只会占用很少的硬件资源。 我们可以将虚拟机视为一种「由软件组成的计算机」,可以使用它来「运行在真实物理计算机上运行的任何软件」。通过将一台物理服务器划分为多个虚拟机并共享资源,可以更有效地利用硬件资源,「提高资源利用率」。 与物理机一样,虚拟机拥有自己的操作系统(Windows、Linux 等)、存储、网络、设置和软件等,并且与在该主机上运行的其他虚拟机完全隔离。 ![]() 「虚拟机可以做什么,有什么好处?」 资源利用率最大化:虚拟机允许在一台物理服务器上同时运行多个虚拟机,从而提高服务器资源的利用率。通过共享处理器、内存和存储等资源,可以更有效地利用硬件资源,降低成本。 灵活性和可扩展性:虚拟机可以根据需要动态分配和调整资源。当应用程序的需求发生变化时,可以根据需要增加或减少虚拟机的数量和资源配额,实现灵活的资源管理和弹性扩展。 硬件无关性:虚拟机屏蔽了底层物理硬件的差异,使得应用程序可以独立于具体的硬件平台运行。这意味着应用程序可以在不同的操作系统和硬件环境中无缝迁移,提供更好的可移植性和兼容性。 隔离性和安全性:虚拟机提供了隔离的运行环境,不同的应用程序或服务可以在各自独立的虚拟机中运行,互不干扰。这种隔离性可以有效防止应用程序之间的冲突或故障相互影响,提高系统的稳定性和安全性。 简化管理和维护:通过虚拟化技术,可以统一管理和监控多个虚拟机,简化系统管理和维护的工作量。可以通过集中管理工具对虚拟机进行统一的配置、备份、恢复和升级,提高管理效率。 开发和测试环境:虚拟机可以用于创建和管理开发和测试环境,使开发人员可以在独立的虚拟机中进行应用程序的开发、测试和调试。这种隔离的开发和测试环境可以有效地模拟真实生产环境,并提供更好的可控性和可重现性。 2、什么是 Docker?「容器化」:容器化是软件开发的一种方法,可以将应用程序和它所依赖的组件、相关的环境变量配置文件等打包成容器,然后在不同的环境中运行。容器技术最流行的实现就是 Docker。Docker 是一种虚拟化容器技术,其设计理念是 "一次构建,到处运行"。 ![]() 举个例子:这就像码头上的集装箱运载货物一样,把货物(应用程序)打包后放在一个集装箱里,假设这个货物是一箱罐头和食用所需的勺子与叉子(依赖环境),通过货轮,货物可以很方便地从一个码头(假设是 Ubuntu 环境)运送到另一个码头(假设是 Centos环境)。在运输期间,货物不会受到任何的损坏(程序文件没有丢失和损坏),所以在另一个码头卸货后,依然可以很好地食用(正常启动)。 ![]() 与虚拟机相比,Docker 以一种轻量级的方式实现了运行空间的隔离。虚拟机拥有的好处,Docker 也都有。打个比方,「如果物理机是一栋写字楼,那么虚拟机就是写字楼当中不同的租赁单位(公司),而 Docker 就是办公室内的隔断或分区」。 从这个比喻中,可以发现 Docker 和虚拟机之间的一些区别: 资源占用:虚拟机是独立的单位,每个虚拟机都需要分配独立的资源,包括处理器、内存和存储空间等,就像不同单位的行政、IT 支持部门;而容器则是办公室内的隔断或分区,它们共享相同的办公室资源,包括操作系统内核和环境配置等,就像同一单位共享同一个 IT 支持部门。因此,相比于虚拟机,容器的资源占用更少,可以更高效地利用硬件资源。 启动时间和性能:由于每个虚拟机需要启动整个操作系统,所以虚拟机的启动时间相对较长。而容器启动速度快,通常在几秒钟内完成启动,因为它们共享主机操作系统内核,不需要启动整个操作系统。虚拟机在性能方面可能会有一定的开销,而容器的性能开销较小,更接近于直接在主机上运行应用程序。 隔离性:虚拟机提供了较强的隔离性,每个虚拟机都运行在独立的操作系统实例中,相互之间隔离,互不影响。而容器是在操作系统层面进行隔离的,它们共享相同的操作系统内核,但通过容器技术实现了进程级别的隔离,使得容器之间相互独立。虚拟机提供了更强的隔离性,适合于需要更高安全性和完全隔离的场景,而容器提供了较轻量级的隔离性,适合于快速启动和高密度部署的场景。 管理和部署:虚拟机的管理和部署相对复杂,需要涉及虚拟机的配置、网络设置等。而容器具有更简化的部署和管理方式,通过使用容器镜像和容器编排工具,可以快速构建、部署和管理容器化应用。 操作系统支持:容器作为一种隔断,不能基于一种内核(Linux)提供另一种内核(Windows)的虚拟化运行环境,所以,基于 Linux 的 Docker 是不支持运行 Windows 应用的(Docker 可以在 Windows 运行,Docker 利用了 Windows 操作系统中的 Hyper-V 虚拟化技术来创建一个轻量级的 Linux 虚拟机,Docker 容器在这个 Linux 虚拟机中运行)。![]() 1.1、镜像 Docker 会把应用程序及依赖打包进镜像(Images)里,提供了容器运行时所需的程序、库、配置文件等,同时还包含了一些为容器运行时准备的一些配置参数(如 volume 卷)。 2.1、容器 容器(Container)是镜像的可运行实例。一个 Docker 镜像可以创建多个容器,镜像和容器的关系,「就像是 JavaScript 中的类和实例的关系一样」。 我们可以使用 Docker 提供的 API 创建、启动、停止、删除容器。在默认情况下,容器与容器、容器与主机在默认情况下是隔离的,拥有自己的独立进程空间、网络配置等。 容器由其镜像以及在创建或者启动容器时提供的配置选项来定义,当容器被删除时,未对容器状态做持久化存储的更改都会消失。 3.1、仓库 镜像构建完成后,可以很容易地在当前宿主机上运行。但是,如果需要在其它服务器上使用这个镜像,就需要一个集中的存储、分发镜像的服务,Docker Hub 就是这样的服务,叫作仓库( Docker Registry )。仓库的概念与 Git 类似,可以理解为 GitHub 这样的托管服务。 一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 : 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 2、安装 Docker参考官网:https://docs.docker.com/get-docker/ 验证安装: $ docker --version输出所安装的 Docker 版本。 3、使用镜像 3.1、获取镜像Docker Hub 上有大量的镜像可以用。从 Docker 镜像仓库获取镜像的命令是 docker pull: $ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] 拉取一个镜像,需要指定 Docker Registry 的地址和端口号,默认是 Docker Hub; 还需要指定仓库名和标签,仓库名和标签可以唯一确定一个镜像,仓库名则由作者名和软件名组成; 而标签是可以省略的,如果省略,则默认使用 latest 作为标签名。以拉取 centos 镜像为例: $ docker pull centos因为省略作者名,则作者名为 library,表示使用 Docker 官方的镜像,所以上面的命令等同于: $ docker pull library/centos:latest 3.2、运行镜像使用 docker run 命令,可以通过镜像创建一个容器: $ docker run -it centos /bin/bash 3.3、列出镜像要想列出已经下载下来的镜像,可以使用 docker image ls 命令或者快捷命令 docker images 。 $ docker images「列出部分镜像」 假设我们拉取了很多镜像,现在想列出 java 仓库中的镜像,可以使用命令: $ docker images java也可以添加标签做进一步的过滤: $ docker images java:8 3.4、删除本地镜像当本地有些镜像我们不再需要时,那我们也可以删除该镜像,以节省存储空间。不过要注意,如果有使用该镜像创建的容器未删除,则不允许删除镜像。 $ docker image rm image_name/image_idimage_name 表示镜像名,image_id 表示镜像 id 。 快捷命令为: $ docker rmi image_name/image_id如果想要删除全部镜像: $ docker rmi $(docker images -q)强制删除全部镜像: $ docker rmi -f $(docker images -q) 4、操作容器 4.1、启动容器启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态的容器重新启动。 「新建并启动:」 $ docker run hello-world如果本地环境中没有 hello-world 镜像,会从远程仓库中拉取镜像;如果有,则使用本地的镜像。 注意:命令执行之后, hello-world 这个容器会自动停止,因为该镜像的目的就是输出一段内容就结束了,但并不是所有的容器运行之后都会停止的。如果需要容器在后台持续运行,可以加一个 -d 参数,-d 参数的作用是在后台运行容器并打印容器 ID。 重新启动停止的容器: $ docker start CONTAINER_ID 4.2、查看容器如果要查看本地的容器,可以使用 docker container ls 命令: $ docker container ls查看所有容器也有简洁的写法,如下: $ docker ps注意,上面两条命令都是列出正在运行的容器。如果想要列出所有容器(包含已停止的容器),可以使用命令: $ docker ps --all或者快捷命令: $ docker ps -a 4.3、停止容器可以使用 docker container stop 来终止一个运行中的容器。也可以使用快捷命令: $ docker stop container_id此外,docker container restart 命令会将一个运行态的容器终止,然后再重新启动它。 4.4、删除容器我们可以使用 docker container rm 命令,或者简洁的写法 docker rm 命令来删除容器。不过不允许删除正在运行的容器,因此如果要删除的话,就必须先停止容器。 $ docker rm container_idcontainer_id 表示容器 id,可以通过 docker ps 查看容器 id 。 当我们需要批量删除所有容器,可以用下面的命令: $ docker rm $(docker ps -aq)删除所有退出的容器: $ docker container prune 4.5、进入容器 $ docker exec -it container_id commandcontainer_id 表示容器的 id,command 表示 linux 命令,如 /bin/bash。 下面的命令则启动一个 bash 终端,允许用户进行交互: $ docker run -it ubuntu:18.04 /bin/bashroot@75053a970732:/#其中,-t 选项让 Docker 分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。可以合起来写成 -it 。 在交互模式下,可以通过所创建的终端来输入命令,例如: root@75053a970732:/# lsbin dev home lib64 mnt proc run srv tmp varboot etc lib media opt root sbin sys usr 三、构建镜像 1、使用 Dockerfile 定制镜像Dockerfile 是一个 Docker 镜像的描述文件,由一行行构建镜像时所需的指令和说明构成。 ![]() 下面以一个定制 nginx 镜像为例。 在一个空白目录中,建立一个文本文件,并命名为 Dockerfile: $ mkdir mynginx$ cd mynginx$ touch DockerfileDockerfile 的内容为: FROM nginxRUN echo 'Hello, Docker!' > /usr/share/nginx/html/index.htmlFROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像,后续的操作都是基于 nginx; RUN:用于执行后面跟着的命令行命令。 1.1、build 命令docker build 命令用于构建镜像,其格式为: $ docker build -t [镜像的名字及标签,通常 name:tag] -f [指定要使用的 Dockerfile 路径] [ContextPath] -t 是 --tag 的简写,用于指定镜像的名字及标签; -f,指定要使用的 Dockerfile 路径; Context(上下文), 当我们构建镜像的时候,经常会需要将一些本地文件复制进镜像(比如通过 COPY 指令、 ADD 指令等)。而使用 docker build 命令构建镜像时,并不是在本机环境中完成的,而是在所安装的 Docker 引擎中完成的。所以这个时候,Docker 引擎无法用到我们本机的文件,就需要把我们本机的指定目录下的内容一起打包(上下文包)提供给 Docker 引擎用来构建镜像。 1.3、构建镜像并启动容器下面使用在 Dockerfile 文件所在目录执行: # 镜像名称为 nginx:test, 上下文为根目录$ docker build -t nginx:test .启动容器: $ docker run -p 8088:80 -d nginx:test -p:指定端口映射,将 nginx 默认的 80 端口映射到主机的 8088 端口; -d:后台运行容器,并返回容器 ID。浏览器访问 http://localhost:8088/ 查看输入内容。 四、编排容器前面介绍的 Dockerfile,它可以用于「构建」一个独立的镜像。而如果涉及多个容器的组合运行(如一个 web 项目,除了 web 服务容器本身,还需要加上数据库服务容器等等),就可以通过 docker-compose 来实现「编排」了。 1、使用 docker-compose有三个步骤: 使用 Dokcerfile 定制所需的镜像(如果不需要定制,可不需要这一步); 编写 docker-compose.yml 文件,定义构建应用程序的服务; 执行 docker-compose up 命令来启动并运行整个应用程序。常用参数: docker-compose up -d,在后台运行; docker-compose ps,列出项目中所有的容器 docker-compose stop,停止正在运行的容器,可以通过docker-compose start 再次启动 docker-compose build,构建(重新构建)项目中的服务容器 docker-compose down,停止和删除容器、网络、卷、镜像。 五、场景实践 1、使用 Docker 搭建 WordPressWordPress 是一个基于 Mysql 和 PHP 的博客应用程序。使用 Docker 来搭建 WordPress,需要两个镜像:Mysql 和 WordPress。 下面使用 docker-compose 来编排这两个镜像: version: '3.8'services: db: image: mysql:5.7 # 持久化数据 HOST:CONTAINER 格式 volumes: - ./db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: your_mysql_root_password MYSQL_DATABASE: your_mysql_database MYSQL_USER: your_mysql_user MYSQL_PASSWORD: your_mysql_password wordpress: image: wordpress:latest volumes: - ./wp_data:/var/www/html ports: - 8000:80 restart: always depends_on: - db environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: your_mysql_user WORDPRESS_DB_PASSWORD: your_mysql_password WORDPRESS_DB_NAME: your_mysql_database# 定义 Docker 卷的集合volumes: db_data: wp_data:在 Docker 中,volumes(卷)是一种用于持久化存储数据的机制。它允许你在容器和宿主机之间共享和保留数据。当你在 Docker 中创建或使用一个卷时,你可以将它挂载到容器的特定路径上,使得容器内的数据可以存储在该卷中。这样做的好处是,即使容器被删除或重新创建,卷中的数据仍然保持不变,不会丢失。这对于持久化存储数据、在容器之间共享数据或与宿主机进行数据交互非常有用。 使用 docker-compose 命令启动容器: $ docker-compose up -d 2、Docker + Nginx 部署 React 应用编写 Dockerfile 文件: # node 镜像# apline 版本的 node 镜像会小很多FROM node:16-alpine3.16 as build-stage# 在容器中创建目录RUN mkdir -p /app# 指定工作空间,后面的指令都会在当前目录下执行WORKDIR /app# 解释说明:# 1、Docker 镜像是分层的。Dockerfile 中的每个指令都会创建一个新的镜像层,每个 RUN 都是一个指令# 2、当 Dockerfile 的指令修改了,或者复制的文件变化了,或者构建镜像时指定的变量变化了,对应的镜像层缓存就会失效# 3、而某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效# 4、镜像层是不可变的,如果我们在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件(只是这个文件在 Docker 容器中不可见了)。# 5、所以我们先拷贝 package.json,然后 RUN npm i 安装依赖,形成一个镜像层,再拷贝其他所有文件,形成一个镜像层; # 之后如果代码有所变动,但是 package.json 没有变动,再次执行时,就不会再安装依赖了,可以节省很多时间。 # package.json 有变动,才会重新执行 RUN npm i 安装依赖。# 拷贝 package.json、package-lock.json 或者 yarn.lockCOPY package.json *.lock ./# 设置 npm 源RUN npm config set registry https://registry.npmmirror.com# 安装依赖RUN npm install# 拷贝其他所有文件到容器(除了 .dockerignore 中的目录和文件)COPY . .# build 项目RUN npm run build# nginx 镜像FROM nginx:alpine# 复制 build 后的文件到 nginx 的指定目录(/usr/share/nginx/html)COPY --from=build-stage /app/build/ /usr/share/nginx/html# 用本地的 default.conf 配置来替换 nginx 镜像里的默认配置COPY nginx/nginx.conf /etc/nginx/nginx.conf# 暴露 80 端口EXPOSE 80# 运行容器时执行命令# 容器启动时执行的那条入口命令一旦结束了,容器也会结束。所以需要将守护关闭,让 nginx 后台运行。CMD ["nginx", "-g", "daemon off;"]使用 Dockerfile 构建 构建镜像 $ docker build -t react_nginx:1.0 . 根据镜像创建容器 $ docker run -p 3000:80 react_nginx:1.0也可以在 docker-compose 中使用这个 Dockerfile 文件进行构建: version: '3'services: web: # 指定 build 配置,使其自动构建镜像并启动容器 build: context: ./ dockerfile: ./Dockerfile image: react_nginx:1.0 ports: - 3000:80 container_name: react_nginx_test运行: $ docker-compose up -d --build 3、Docker 部署 node 服务部署一个 node + nest.js + mysql 的应用服务,需要使用 node 和 mysql 两个基础镜像。 编写 Dockerfile: FROM node:16-alpine3.16 as build-stage# 指定工作空间,后面的指令都会在当前目录下执行WORKDIR /usr/src/appCOPY package.json *.lock ./RUN npm config set registry https://registry.npmmirror.comRUN yarn installCOPY . /usr/src/appRUN yarn buildEXPOSE 7001CMD ["node", "dist/main.js"]使用 docker-compose 编排镜像: version: '3.9'services: database: platform: linux/x86_64 image: mysql:5.7 restart: always container_name: db ports: - '3306:3306' volumes: - ./data/mysql:/var/lib/mysql - ./doc/mysql-init/:/docker-entrypoint-initdb.d networks: - nesjs-network env_file: - .env server: image: node:current-alpine3.11 container_name: nestjs build: context: . dockerfile: Dockerfile ports: - '7001:7001' depends_on: - database networks: - nesjs-network restart: always links: - database env_file: - .env volumes: - .:/app - /app/node_modules command: npm run start:prodnetworks: nesjs-network: driver: bridge name: nesjs-network运行: $ docker-compose up -d --build在 postman 中调试接口: ![]() |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |