记录我们迁移到 Docker 的挑战和经验教训

Docker中容器的备份、恢复和迁移 转自:http://www.linuxidc.com/Linux/2015-08/121184.htm 1. 备份容器 首先,为了备份Docker中的容器,我们会想看看我们想要备份的容器列表。要达成该目的,我们需要在我们运行着Docker引擎,并已创建了容器的Linux机器中运行 docker ps 命令。 # docker ps Docker Containers ... 阅读详情

几周之前,我们宣布了 最新的产品 发布,以及由容器技术和 Docker 支持的 Artifakt 平台的全新的任意 App 功能。

在过去几年中,Artifakt 一直专注于 PHP 栈。但 PHP 并不是 Web 应用程序的唯一语言。通过使用 Docker 集成,我们提前完成了宏伟的计划!

基于应用程序打包的事实标准来重新调整我们的 PaaS,对于各种形式和规模的开发团队来说都是一个好消息。

在这个版本中,你会发现许多额外的功能,在代码、更改可跟踪性、运行时性能和客户价值等方面,现在是加入容器友好型 PaaS 基础设施的最佳时机。更不用说,Docker 是 DevOps 核心原则(敏捷性、抗敏捷性和上市时间)的最好朋友。

但所有的旅程,无论结果如何,通常都伴随着奋斗。在本文中,我想要深入讨论我们在迁移到 Docker 的过程中所面临的挑战和我们学到的经验教训。

如果你想要迁移到容器,请读一读本文——我相信你至少会找到一点相关信息,也许我们处理某些问题和挑战的方案可以帮助你避免一些潜在的错误。

问题:软件工程中没有免费的午餐

PaaS 解决方案非常方便。我相信任何从本地部署服务或 IaaS 迁移其应用程序到 PaaS 的人都会同意。

其中很方便的一点是虚拟机(Virtual Machines,VM)的使用。这是一款很好的软件,几十年来至今,都非常安全和成熟。现在没有人做事情能离得开它们,所以它们是非常必要的。尽管如此,这还不够。

虚拟机的阴暗面是,它们倾向于作为私人宠物成长。日常维护、定期支持和偶尔的急救支持需要大量的固定成本以及人为协助。

现在,面对痛苦的现实:虚拟机已经不再适应云基础设施。目前的条件对它们来说是苛刻的,可能采用严格的规章制度。尽管科技领域不断发展,但虚拟机仍然建立在 20 年前相同的原则上。

放大:哪里会出问题

你应该时刻记住所有可能出错的情况并做好准备。让我们看一看容器迁移过程中可能出现的几个问题。

不良后果 #1:速度不够快

我们以前都听过,速度是所有战斗之母。不仅是在战略上,而且从构思到执行都是如此。变化需要快速发生,跟上生态系统的快速进化。正如通用电气前 CEO 杰克·韦尔奇(Jack Welch)所说:“如果外部变化的速度超过内部变化的速度,终结就不远了。”

不是大吃小,而是快吃慢。拥有好主意,但是执行慢,意味着死刑。拥有糟糕的主意,但是执行良好,意味着你仍然可以调整和实验直到适应市场获得成功。

不良后果 #2:缺乏自信

如果你在一个软件项目中听过“但是......它在我的笔记本电脑上可以运行!”,请举手——我怀疑我会看到很多人举手。当然,我们有代码、持续集成和所有现代机器等基础设施。别误会,有一些本地优化确实非常有用。但真正有用的是打破局限,将团队提升到足够高的成熟度水平,以便“谁构建谁运行”。

我们不希望 PaaS 成为新的“运维问题”和“支持问题”。还记得“灾难女孩”咒语吗?黑暗运维更加危险,你不希望开发团队自己运行容器, 并在你的防火墙上戳洞 。

是什么触发了变革的需要以及我们向 Docker 的迁移?

容器是上述所有挑战的答案——一个成熟、甚至枯燥的软件打包标准。但情况并非总是如此。

回想 20 世纪,全球化是通过一个非常具体的物质变化实现的:一个通用的箱子来移动汽车、食品等等。这就是我们今天所知道的“多式联运(inter-modal transportation)”。

图片来源:Docker Inc.

自 2014 年以来,软件容器在 Docker Inc.公司旗下的事实解决方案中迅速成熟,并有一个简单却有效的承诺:

“无论底层执行系统是什么,Docker 都可以使用完全相同的代码逐字节运行它。”

图片来源:Docker Inc.

我们敢说,在 Artifakt,容器已经在后台运行了好几个月,即使是有状态的东西。我们现在可以在几秒中内运行不同的配置更改,而不是需要 10 到 30 分钟的虚拟机配置。

在我们的下一个主要控制台版本中,Artifakt 将容器作为部署单元公开。

转变与见证:我们如何让 Magento 2 更加闪亮

你可以想象 Docker 迁移对我们日常工作的开创性影响。协调虚拟机需要与我们的云提供商在某种专有技术上进行强耦合。对于 AWS 来说,是 CloudFormation 和 OpsWorks。我们花了很多时间消化云的复杂性,这样我们亲爱的客户就不必这么做了。

最终,出色的重写让我们拥有了开源和开放格式:Dockerfile、docker-compose.yaml 和稳定的 Docker API。

在笔记本上运行完全相同的 Magento 2 栈并将其投入生产如何?这在 Artifakt 是可能的。

Magento 2 是自 7 月早些时候发布 Stack v5 以来我们正式支持的九个运行时的一部分。在许多方面,这个发布版本将所有挑战集中在一个地方:

  • crontab 管理

  • 容器测试

  • 部署过程

  • ISO 生产环境本地堆栈

让我们来看看我们是如何克服这些挑战的,以及这将给我们带来什么。Docker 迁移部分 I: 好的方面先从 Docker 的好处开始。我们已经意识到在 PaaS 环境中容器化的好处。有些方面真的很容易实现。成熟度足够高,生态系统蓬勃发展,云供应商已经为未来几年铺平了道路。

我们不可能一一讲述所有的好处,很多好处在 2021 年讲都会很无聊,所以让我把重点放在最有启发性的事情上。

好处 #1:使用 Argo 的工作流引擎

Argo Workflows 是实现响应式 GitOps 管道的一个非常好的工具。要讲的有很多,让我们拆开来一个个讲。GitOps 使团队能够执行 Git 中的更改,而不仅仅是代码更改,比如基础设施、网络、存储等。机器的每一个部分,创建、升级或停用,都可以链接到一个 Git 提交。

感觉兴奋吗?我们确实很兴奋!我们的工作流很好地隐藏在 Argo 中,可以为许多不同的堆栈和语言运行部署任务等基础操作。

我们组织中的每个人都可以访问过去的工作流及其日志,从而轻松解决问题。我们现在受益于一个共享的平台,客户支持和工程团队可以帮助客户测量和优化他们的流程,而不是将日志分散在许多复杂的层次上。

在未来,我们也期待着尝试 Argo CD 以及它为像 Artifakt 这样的 PaaS 产品提供的许多机会。

好处 #2:在容器中格式化和测试

事实证明,Docker 镜像有很多出错的方式。由于自动测试在代码中是一种很好的实践,同样的原则也适用于 Dockerfiles。官方文档已经确保了 Dockerfile 的正确性:所有命令都应该返回 0,否则构建将失败。

我们需要在这里增加两个维度:有效性和内容。有效性确保我们在编写 Dockerfile 和语义内容检查时具有正确的风格。

我们可以只使用本机 Dockerfile 指令完成所有操作吗?几乎可以,但是即使如此,它也会导致包含许多非生产层的膨胀镜像,然后进入多阶段构建,等等。

换句话说,如果构建成功,它必须装载恰当数量的正确软件。

因此,我们选择遵循关注点分离的原则,并在测试、验证和语义检查之间划清界限。

对于简单的语法格式化,我们使用 hadolint,这是针对 Dockerfiles 的一种格式化工具。它功能强大,很容易上手,可以与持续集成/持续部署很好地集成,并得到了积极的维护。当然,它本身就存在于一个 Docker 镜像中!让我们看一下基本选项:

hadolint - Dockerfile Linter written in Haskell

Usage: hadolint [-v|--version] [--no-fail] [--no-color] [-c|--config FILENAME]            	[-V|--verbose] [-f|--format ARG] [DOCKERFILE...]            	[--error RULECODE] [--warning RULECODE] [--info RULECODE]            	[--style RULECODE] [--ignore RULECODE]            	[--trusted-registry REGISTRY (e.g. docker.io)]            	[--require-label LABELSCHEMA (e.g. maintainer:text)]            	[--strict-labels] [-t|--failure-threshold THRESHOLD]            	[--file-path-in-report FILEPATHINREPORT]  Lint Dockerfile for errors and best practices

复制代码

在默认的帮助屏幕上,我们可以看到一系列不错的选项和示例:检查所需选项、以不同格式输出报告、声明私有的受信任的注册表等。

要在持续集成中包含 hadolint ,我们建议以下三个步骤:

  1. 使用--no-fail 调用 hadolint ,并在不中断当前流的情况下安全地评估结果。

  2. 在使用选项并找到恰当的平衡点后,对测试的 Dockerfile 进行必要的修复。

  3. 删除--no-fail 选项,并将 hadolint 作为强制步骤启用。

为了演示 hadolint 有多好,让我们看一下我们的 Docker 基础镜像中的这条简单命令:

$ docker run --rm -i hadolint/hadolint:v2.6.0 hadolint - < ./akeneo/5-apache/Dockerfile

接着会给出一个附带严重程度(从 style 到 error)的建议列表,附带有具体的行号,非常整洁。例如:

-:16 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check-:17 DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`-:17 DL3059 info: Multiple consecutive `RUN` instructions. Consider consolidation.

复制代码

所有规则,70 多条,都在 官方库的wiki中 有参考和解释。它们包括非常基础的简单检查(“不要使用 apt-get upgrade”)到高度专业化的用例(“运行 yarn install 之后,没有运行 yarn cache clean”)。

结合在一起,hadolint 选项更加强大。看看这个命令:

docker run --rm -i hadolint/hadolint:v2.6.0 hadolint --require-label author:text --ignore=DL4006 --failure-threshold=warning - ./Dockerfile

在这段代码中,我们告诉 hadolint 去扫描我们的 Dockerfile 文件,通过检查一个强制标签 author ,除了 DL4006 规则,最后,只有在反馈包含警告时才会失败,从而忽略 style 和 info 级别。

对于开发人员来说,hadolint 还支持 Dockerfile 中的 #ignore 内联注解,这使得在一组 Dockerfile 文件上使用相同的命令更容易。

总而言之,这为我们的测试提供了一个良好的开端。稍后,当我们准备好应用更高级别的良好实践时,我们可以降低错误阈值到 notice 。

拥有语法正确且遵循良好实践的 Docker 镜像是非常棒的。现在,我们还需要检查内容的有效性。毕竟,PaaS 产品应该有一套应用的内部规则。

为此,我们使用了另一个很棒的工具——谷歌的 container-structure-test 。它是 Github 上 GoogleContainerTools 命名空间的一部分,在这个命名空间下还托管了一些你可能已经知道或使用过的著名项目:Skaffold、distroless、Jib 和 Kaniko。

Container-structure-test 是一个开源项目,读取测试套件并对照现有的 Docker 镜像进行检查。它有一个命令:test 。注意,这与 hadolint 不同,hadolint 只需要一个纯文本的 Dockerfile 文件就足够了。Container-structure-test 需要一个二进制构件:Docker 镜像或者一个导出为.tar 的文件。和 hadolint 一样,测试也是用普通的 YAML 编写的,这似乎是云生态系统中第二有用的技能(仅次于 Git,对吧?)。下面是用 YAML 编写的一个有意思的声明式测试示例:

schemaVersion: '2.0.0'metadataTest:  labels:	- key: 'vendor'  	value: 'Artifakt'	- key: 'author'  	value: "^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"  	isRegex: true  volumes: []  entrypoint: ["/usr/local/bin/docker-entrypoint.sh"]

fileExistenceTests:- name: 'bash'  path: '/bin/bash'  shouldExist: true  permissions: '-rwxr-xr-x'  uid: 0  gid: 0  isExecutableBy: 'any'

commandTests:  - name: "debian based server"	command: "which"	args: [ "apt-get"]	expectedOutput: ['/usr/bin/apt-get']

复制代码

在这个代码块中,我们测试了一个镜像的元数据、文件和命令结果,分别由 metadataTest 、fileExistenceTests 和 commandTests 三个主键定义。

但是为什么 container-structure-test 需要一个预先存在的构建步骤呢?因为,在后台,它在活跃容器上使用 docker exec 命令来运行每一个测试。最重要的是,由于一个容器只能运行一个测试,所以测试也保证是隔离的。

当你运行测试时使用--save 选项来保持容器,这个行为就很容易查看。让我们在一个官方镜像上运行如下测试:

container-structure-test test --image registry.artifakt.io/sylius:1.10-apache --save --config ./global.yaml

检查保存的容器:

caae8bd3159c    	678b262bc2d6                          	"NOOP_COMMAND_DO_NOT…"   2 minutes ago   	Created                                    	practical_einstein3b63b4f5fcd1    	registry.artifakt.io/sylius:1.10-apache   "NOOP_COMMAND_DO_NOT…"   2 minutes ago   	Created                                    	admiring_solomon44497e1d88cf    	d10ef6baba46                          	"which apt-get"      	2 minutes ago   	Exited (0) 2 minutes ago                   	bold_tesla6e87be191af3    	registry.artifakt.io/sylius:1.10-apache   "NOOP_COMMAND_DO_NOT…"   2 minutes ago   	Created                                    	angry_bouman

复制代码

当你想使用 docker logs 或 docker diff 检查保存的容器以及它们如何受影响时,这非常有用。使用最后一个命令,我们可以轻松编写一个测试来确保我们的容器是足够无状态的,或者不会泄露意料外的文件,或者对活跃容器进行任何其它评估。

正如我们在第一个示例中已经提到的,container-structure-test 评估三类开箱即用的检查:镜像元数据(labels、volumes 和 entrypoints 等等)、文件是否存在、任意命令结果。

在测试是否存在的基础上,我们还编写测试来检查最终 Docker 镜像中我们不需要的内容。想想开发包、编译器和工具,它们可能到处都是,在生产环境肯定不受欢迎。防止这种情况的一种方法是:

fileExistenceTests:- name: 'forbid gcc'  path: '/usr/bin/gcc'  shouldExist: false

复制代码

最后,另一个有用的选项是将 setup 关键词与测试命令结合使用。有些测试只在 Docker 入口点运行之后才有意义。我们使用 setup 键来处理这种情况。请看下面的示例:

- name: "check mounted folder private"	setup: [["/usr/local/bin/docker-entrypoint.sh"]]	command: "ls"	args: [ "-la", "/opt/drupal/web/sites/default/private"]	expectedOutput: [ 'lrwxrwxrwx 1 www-data www-data .+ /opt/drupal/web/sites/default/private -> /data/web/sites/default/private' ]

复制代码

官方文档和高级案例中还有很多功能,比如测试守护进程,因此我鼓励你们进行深入研究。

Docker 迁移部分 II:坏的方面(和有趣的方面!)

在容器化的道路上,许多挑战是预料不到的,由于我们获取了一些有价值的见解,因此我们必须分享其中一些挑战。

挑战 #1:crontab 集成

我们最完整的运行时是 Magento 2 和 Akeneo,它们是 cron 任务的重度用户:索引、缓存、镜像大小调整、导入/导出等等。

Docker 对于异步间歇进程处理得怎么样?其实并不太好。Docker 101 中众所周知,你不能在与主进程相同的容器中运行 cron。

那么,有效的替代方案是什么?我们考虑了以下几个方案:

  • Swarm cronjob

  • cron job containers

  • Docker exec bridge

首先,Docker 刚刚升级了 Swarm 编排层来运行 cron 作业,就像 Kubernetes 那样。这可能行得通,但是 Swarm 不在我们最初的路线图上。

其次,我们可以为每个 cron 作业运行额外的容器,在节点级别使用一个 cron 守护进程。这个方法有利有弊。由于时间和计划的限制,我们不得不加快步伐。

最后,我们可以声明将 crontab 保持在节点级别,并使用 docker exec 将命令运行到活跃的容器中。这可能起作用,因为我们仍然在每个服务器上运行一个应用程序容器,所以现在这是有意义的。

我们选择了最后一个选项,结果是简单、优化,并且尊重我们热爱的 Linux 精神。下面是将 cron 作业注入到活跃容器的三个简单步骤:

步骤 1

编写一个 docker exec 包装器,其中实际上有 2 行代码足以指向<cID> 容器。

#!/bin/bashsudo docker exec -t <cID> sh -c "$2"

复制代码

步骤 2

将包装器保存在 crontab 用户空间的某个地方(我们将其命名为 dockercron.sh)。

用你的脚本添加/替换默认的 contab SHELL env. var :

### Crontab Managed By Artifakt ###SHELL=/home/ec2-user/dockercron.sh5/* * * * * uptime > /tmp/uptime.txt

复制代码

步骤 3

运行 docker events 并检查 crontab 是否正在调用应用程序容器:

2021-07-28T13:55:02.338665047Z container exec_create: sh -c uptime > /tmp/uptime.txt a360afb6e (artifakt.io/image=616787838396.dkr.ecr.eu-west-1.amazonaws.com/sylius, execID=8b14a4e96eb5175c74b689260e1b692af34f22260e9572fbd2bb2c2b663a3c1e, image=616787838396.dkr.ecr.eu-west-1.amazonaws.com/sylius:1.10, vendor=Artifakt)2021-07-28T13:55:02.339417333Z container exec_start: sh -c uptime > /tmp/uptime.txt a360afb6e (artifakt.io/image=616787838396.dkr.ecr.eu-west-1.amazonaws.com/sylius, execID=8b14a4e96eb5175c74b689260e1b692af34f22260e9572fbd2bb2c2b663a3c1e, image=616787838396.dkr.ecr.eu-west-1.amazonaws.com/sylius:1.10, vendor=Artifakt)2021-07-28T13:55:02.822814763Z container exec_die a360afb6e  (artifakt.io/image=616787838396.dkr.ecr.eu-west-1.amazonaws.com/sylius, execID=8b14a4e96eb5175c74b689260e1b692af34f22260e9572fbd2bb2c2b663a3c1e, exitCode=0, image=616787838396.dkr.ecr.eu-west-1.amazonaws.com/sylius:1.10, vendor=Artifakt)

复制代码

这个方案保持了完全相同的执行环境,同时将资源使用保持在一个容器中,保证了总体稳定性。

挑战 #2:取消 OpsWorks

取消一个工作多年的遗留层几乎是不可能的。因此,说实话,我们并没有完全成功。然而,我们尽了最大的努力,设法使这一层尽可能无关紧要。

从 OpsWorks 到 Docker 的转变,需要将移除过去的平台规则,并转移到编写 docker-compose YAML 和 bash 脚本。结果是我们所有的部署都是一个独特的分支。

经过快速的多次提交,并经过许多尝试和错误后,OpsWorks 现在所做的就是安装 Docker Engine 以及屈指可数的一些容器依赖项。

其它一切都是通过 Docker API 操作,由普通的过去的 OpsWorks 作业触发,比以往任何时候都更可预测。

这是简化和技术债务平抑的一个伟大里程碑!

挑战 #3:本地运行 HTTPS

当我们接近发布时间时,我们的 CEO 看了看我们的 demo,说:“嘿,如果开发者可以用 HTTPS 本地运行他们的应用程序,那就太好了”。作为开发者,团队中的每个人都马上理解了这个机遇。

工作站越接近生产环境,我们送出的 bug 就越少。这是表达 12因素应用程序 的 第10章 ——“dev/prod 对等”的另一种方式。

下面是我们如何做到的。只需要 2 个附加组件(容器!): Nginx-proxy 和 Cert companion 。我们使用它们修改了原始的 docker-compose.yaml ,除此之外没有修改其它代码:

version: '3'services:  proxy:	image: jwilder/nginx-proxy	container_name: base-wordpress-proxy	restart: always	ports:    	  - "8000:80"    	  - "8443:443"	volumes:    	  - /var/run/docker.sock:/tmp/docker.sock:ro    	  - ./certs:/etc/nginx/certs

  proxy-companion:	image: nginx-proxy-companion:latest	restart: always	environment:  	  - "NGINX_PROXY_CONTAINER=base-wordpress-proxy"	volumes:    	  - /var/run/docker.sock:/var/run/docker.sock:ro    	  - ./certs:/etc/nginx/certs

复制代码

最后,为了使这个设置生效,我们的应用程序容器还有两个 env.变量是很重要的,因此我们按如下方式添加了它们:

 app:	image: base-wordpress:5-apache	volumes:  	  - ".:/var/www/html"	environment:    	  VIRTUAL_HOST: "localhost"  	  SELF_SIGNED_HOST: "localhost"

复制代码

在第一次运行时,nginx 寻找一个 ca.cert ,如果不存在就在线为你生成一个。然后,我们必须告诉浏览器要像信任其它 CA 一样信任这个 ca.cert 。遗憾的是,这仍然需要一次手工设置。

我们尝试了 Let's Encrypt 等各种方案,但没有开箱即用的解决方案。 你不能使用Let's Encrypt作为一个CA来提供本地主机证书。

最后,还需要一些额外的步骤,通常会弄乱本地的根证书。下面是我们为开发人员找到的一条最短路径,即一次性安装本地证书颁发机构并在所有本地开发堆栈上使用它。请注意,以下步骤仅适用于 Google Chrome。

  1. 打开 Chrome 设置并搜索“certificates”。

  2. 打开 Manage Certificates 菜单,它会弹出密钥链入口。

  3. 在 System 密钥链,打开 Certificate 选项卡,将 ca.cert 从 Nginx-Proxy Companion 中删除。

  4. 双击 Nginx-proxy Companion 证书为 Always Trust。

Docker 迁移部分 III:

前方我们还有很多方法可以让一个好的平台更好。以下是我们正在考虑的下一步行动。

持久化数据

我们严重依赖 AWS 持久化数据。这已经 在弹性和可伸缩性方面发挥了神奇的作用 。我们的客户需要他们的数据安全且封闭。另一方面,开发者更喜欢便利性和易用性。

网络带宽

由于速度是一种竞争优势,我们正朝着更快的部署迈进。Docker 镜像可能会变大,构建任意代码的速度会变得非常慢。我们希望在未来实施的一些最佳实践包括:

  • 代理依赖管理器(例如 composer、npm、maven)

  • Docker 层缓存,而不是原始构建环境

  • 从一个构建到另一个构建的共享数据卷

  • 构建并推动镜像更接近生产环境,而不是通过区域移动

这些步骤可以显著减少延迟,我强烈建议你试一试。

Docker 构建中的高级用例

一些高级 Docker 镜像需要一个实时数据库来完成构建阶段。这听起来有点儿奇怪,但我们经常看到这样的情况。我们正考虑以下几条实例:

  • 为构建单独绑定一个虚拟数据库

  • 当兼容的时候,使用 SQLite 作为卷——不需要服务器

随你发挥,容器化的方案很多样化,并不枯燥!

以上就是我们迁移到 Docker 的经历。如果你当前正在迁移到容器或者希望迁移到容器,我希望你能够在本文中找到一些有用的点子。

Docker 镜像与容器的备份迁移 Docker镜像与容器的备份迁移 阅读详情

相关推荐

Docker迁移数据卷,迁移容器详解(测试通过)

最近工作上有需求要迁移现在docker上的容器和数据到新的服务器上, 但网上搜了很多博客, 真正实用且有效的寥寥无几, 最后自己爬了不少坑干掉了这个需求, 写博客记录一下操作过程, 希望后来的小伙伴能够少走些弯路! 接下来的操作根据mongoDB数据库的迁移举例! 一 查看当前mongo容器挂载的数据卷, 找到容器数据卷信息 docker inspect mongo Mounts属性就...

Ghostbamboo的博客 6458

容器技术(云迁移与灾备)

容器技术(云迁移与灾备)

If your heart is restless, smile calmly! 741

Docker入门到实践 (五) docker数据的备份、恢复与迁移

文章目录一、前言二、docker数据的备份、恢复与迁移方式一:docker容器的备份、恢复与迁移1、docker容器的备份 (导出)2、docker容器的迁移与恢复 (导入)方式二:docker镜像的备份、恢复与迁移1、docker镜像的备份 (导出)2、docker镜像的迁移与恢复 (导入)方式三:docker数据卷的备份、恢复与迁移1、docker数据卷的备份 (导出)2、docker数据卷的...

浅末年华的博客 1万+

如何将一个已有的应用程序迁移到Docker容器中

参数用于将容器内部的端口映射到宿主机的端口,这里将容器的 3000 端口映射到宿主机的 3000 端口。启动容器后,在浏览器中访问。如果应用程序需要持久化存储数据,如数据库数据,需要使用 Docker 卷(Volume)来实现数据的持久化。命令构建 Docker 镜像。命令启动一个容器来测试镜像是否正常工作。参数用于指定镜像的标签,格式为。表示使用当前目录作为构建上下文。,检查应用是否能够正常访问。中的指令,逐步构建镜像。参数表示容器在后台运行。在项目根目录下,使用。构建完成后,可以使用。

游戏全栈,技术合作 1239

[USACO2023-JAN-Bronze] T2 Air Cownditioning II 题解

[USACO2023-JAN-Bronze] T2 Air Cownditioning II题解

1652

RC滤波电路实战解析:无源与有源设计的性能对比与应用选择

本文深入解析了RC滤波电路的核心原理,重点对比了无源滤波电路与有源滤波电路的性能差异。文章通过实测波形与仿真数据,详细阐述了两者在带载能力、频率响应精度、噪声特性等方面的优劣,并提供了清晰的应用选择指南,帮助工程师根据信号属性、负载条件和性能要求做出最优设计决策。

weixin_29268637的博客 431

容器的迁移与备份

说明 工作中我们会遇到把当前机器的容器迁移到另外一台机器。此时我们就需要进行容器的备份与迁移。 容器保存为镜像 比如当前容器名为:mynginx 把这个容器保存为镜像 docker commit mynginx mynginx_1 镜像备份 通过以下命令将镜像保存为tar文件 -o:输出 docker save -o mynginx.tar mynginx_1 镜像的恢复和迁移 将备份的镜像tar恢复成一个镜像 -i:输入 docker load -i mynginx.tar

奈斯菟咪踢呦 687

java结合Ai

Spring AI 是 AI 工程的应用框架。其目标是将Spring生态系统的设计原则(如可移植性和模块化设计)应用于AI领域,并促进使用POJO作为应用程序的构建块到AI领域。特征跨 AI 提供商的可移植 API 支持,适用于聊天、文本到图像和嵌入模型。支持同步 API 和流 API 选项。还支持下拉以访问特定于模型的功能。聊天模型亚马逊基岩人类学Cohere的命令AI21 Labs的侏罗纪-2Meta 的 LLama亚马逊的泰坦人类学克劳德Azure 开放式 AI。

qq_67832732的博客 2850

鲲鹏云计算解决方案“-容器迁移实验

鲲鹏云计算解决方案"-容器迁移实验实验简介Docker安装检查内核版本移除旧的版本安装Docker依赖工具。Docker构建基础镜像任务3 Docker根据基础镜像安装Redis验证Redis镜像 实验简介 通过Docker安装,构建基础镜像,根据基础镜像安装Redis,验证Redis镜像等模块的实验练习和实训,让学员掌握容器的迁移指导。 实验目的 掌握Docker安装。 掌握Docker构建基础镜像。 掌握Docker根据基础镜像安装Redis。 掌握验证构建的Redis镜像。 实验环境 华为云鲲鹏虚拟

hnw13938056090的博客 955

3D Slicer5.7在win11下的源码编译安装

本博客主要参考官方安装文档以及部分优快云的博客,部分内容的书写会直接参考官方文档的内容。

Topsort的博客 4761

SigmaStar(星宸科技)SSC33X系列

目前,SSC33X系列已经量产了接近两年,SDK成熟稳定,功耗表现良好,图像效果出色,广泛应用在AI枪机、AI球机、AI云台机、多目摄像机、停车场闸机、人脸门禁、人脸锁、门铃猫眼等产品上。

Comake Online的博客 1万+

记录我们迁移到 Docker 的挑战和经验教训,2024届毕业生还没找到Java开发工作

在这个代码块中,我们测试了一个镜像的元数据、文件和命令结果,分别由 metadataTest 、fileExistenceTests 和 commandTests 三个主键定义。但是为什么 container-structure-test 需要一个预先存在的构建步骤呢?因为,在后台,它在活跃容器上使用 docker exec 命令来运行每一个测试。最重要的是,由于一个容器只能运行一个测试,所以测试也保证是隔离的。当你运行测试时使用–save 选项来保持容器,这个行为就很容易查看。

m0_58269520的博客 1021

configure: error: no acceptable C compiler found in $PATH解决方案

本文主要介绍了configure: error: no acceptable C compiler found in $PATH解决方案,希望能对使用Linux的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 4万+

docker容器迁移操作记录

如果迁移容器不能满足要求,就只能使用docker commit命令生成旧容器镜像,再迁移。:如果迁移容器不能满足要求,就只能使用docker commit命令生成旧容器镜像,再迁移。:增加了/data/mysql/my.cnf下一个配置,防止应用连接数据库时被拒。236上的mysql是build生成的,不确定修改内容,所以采用容器导出方式迁移。说明:旧confluence没有初始化,未启用。说明: 服务已启动,需要研发登录确认数据。

shijin741231的博客 4124

【100%通过率】2023华为od机试C卷【电脑病毒感染】Java&Go 实现

一个局域网内有很多台电脑,分别标注为 0 ~ N-1 的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t 表示。其中网络内一台电脑被病毒感染,求其感染网络内所有的电脑最少需要多长时间。如果最后有电脑不会感染,则返回-1.

MISAYAONE的博客 2863

pt100和max31865测室温跳变比较大,会从23.04跳到23.47,23.75反复跳变超过了0.5的误差范围,在VDD和GND之间加上0.1和10的滤波电容也不行,如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 2088

【Docker】docker安装记录

Windows安装Docker的安装记录。

chendi8的博客 2229

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

harbor以及docker镜像迁移记录

将 Docker 数据根目录从 /var/lib/docker 迁移到 /data2/docker

weixin_74812406的博客 717

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

群晖docker套件迁移

关键步骤就是第三部迁移共享文件夹,因为我是放在单独的共享文件夹内整体迁移,所以迁移后容器也不用做任何修改。如果有情况不一样的,应该举一反三,将容器的相关文件路径映射和迁移后的容器配置文件路径相匹配应该也是一样的效果。

bear的博客 8631

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

基于 Docker 的 Gitlab 环境迁移遇坑记录

目录(1)迁移准备工作1.1 停掉gitlab1.2 拷贝giblab1.3(2)填坑 因为安全需要,公司的gitlab需要从外网迁移到内网。按道理说公司的gitlab是用的docker部署,直接把原来的docker整个目录复制过来就可以,但是直接复制的会导致gitlab启动不了,中间遇到各种坑,这里记录下可能会帮助到有缘人,O(∩_∩)O哈哈~。 基础环境 操作系统:Ubuntu 18.04 容器环境:Docker version 20.10.12 / docker-compose version G

野生C猿的专栏 4081

服务器迁移记录

使用 Portainer 可以在网页端访问容器,浏览器访问 http://你的ip:9000。然后在配置好新服务器的mysql之后,在新的服务器中输入。然后可以在这里访问MySQL命令行。输入密码后稍等片刻即可导入成功。再来个Portainer。

Gettler的博客 1万+

Flarum论坛docker搭建+迁移记录

本文记录了将Flarum论坛从传统安装方式迁移到Docker容器环境的过程,针对crazymax/flarum容器进行了迁移,确保插件和资源能够正确恢复。

weixin_44413679的博客 1046

Linux 系统盘空间不足,想要将 Docker 镜像和容器数据迁移到数据盘

大家在Linux上用Docker部署项目的时候,有时候会部署多个项目,系统盘空间不足,数据盘又挂载有很多空间,这时候就会想要将 Docker 镜像和容器数据迁移到数据盘,本文主要讲解迁移步骤和迁移过程中遇到的一些坑,记录给大家避免再次入坑。

小相探索IT世界 4077

Windows下Docker数据迁移

Windows下Docker数据迁移问题解决 本文记录了将Docker数据从C盘迁移到其他磁盘的过程。通常Docker Desktop会在WSL中创建两个分发(docker-desktop和docker-desktop-data),但作者遇到只有一个分发的情况。常规迁移方法无效后,尝试直接修改Docker设置中的Disk image location路径,发现存在多种不确定情况:可能只有部分数据迁移、或新建空数据文件。最终解决方案是在完全迁移后,手动将备份的docker_data.vhdx文件复制到新位置。

qq_41831033的博客 1702

docker容器迁移教程

被领导要求部署一个和测试环境一样的演示环境,并且数据库也要同步过去,服务器上的各种服务都是docker部署的,由于之前docker玩的比较少,所以还是踩了不少坑的,在此记录一下正确的操作方法。 例如我需要备份nginx镜像: 备份完成之后可以在目录下查看到这个备份文件 在我们需要迁移的目标机器上执行指令 回车之后会提示是否输入密码,先yes然后输入密码,输入一下root密码即可,如果你是非root用户,可能要注意下文件权限问题 3.镜像备份文件读取 使用docker load载入镜像

Aunero的博客 9504
上一篇: ACID 过时?用 Sagas 搞定数据一致性
下一篇: 代码都写不完,还写个锤子注释!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值