资讯详情

Knative Serving 实战:用 Elixir + Phoenix 构建并部署 Hello World 服务

📅 2026/10/13 6:16:06 | 华诺云谱 👁 阅读
Knative Serving 实战:用 Elixir + Phoenix 构建并部署 Hello World 服务
文档教程云原生【免费下载链接】docsUser documentation for Knative components.项目地址https://gitcode.com/gh_mirrors/docs1/docs点击查看免费下载本篇技术指南以 Knative 官方代码示例仓库中的 helloworld-elixir 为蓝本完整演示如何使用 Elixir 语言与 Phoenix 框架编写一个打印全部环境变量的 Web 应用并将其打包成容器、部署到 Knative Serving最终通过自动扩缩容的 Serverless 方式对外提供服务。读完本文你将掌握 Elixir/Phoenix 项目的本地开发流程、基于 Distillery 的生产发布构建Dockerfile 多阶段打包、KnativeService资源定义以及从kubectl apply到curl验证的完整部署链路。示例概览一个打印环境变量的 Phoenix 应用该示例是一个基于 Phoenix Framework 的极简 Web 应用核心功能是访问首页时把容器内全部环境变量原样输出到页面上。它不依赖数据库也不需要额外的中间件非常适合用来验证 Knative 环境变量的注入机制和服务的连通性。从仓库源码看应用的请求处理链路非常清晰router.ex 将根路径GET /路由到HelloWeb.PageController的index动作page_controller.ex 通过System.get_env()一次性读取全部环境变量从中取出TARGET变量连同环境字典一起交给模板渲染index.html.eex 模板在页面主体展示欢迎语、$TARGET的值并用循环把环境变量逐行输出。# lib/hello_web/controllers/page_controller.ex defmodule HelloWeb.PageController do use HelloWeb, :controller def index(conn, params) do env System.get_env() target Map.get(env, TARGET) render conn, index.html, title: Hello Knative, greeting: Welcome to Knative and Elixir, target: target, env: env end end对应的模板则把target与环境变量字典渲染成 HTML%# lib/hello_web/templates/page/index.html.eex % div classjumbotron h2% greeting %/h2 p$TARGET % target %/p /div h3Environment/h3 ul % for key - Enum.sort(Map.keys(env)) do % li% key % % Map.get(env, key) %/li % end % /ul应用的功能正确性在仓库测试中也有印证page_controller_test.exs 断言GET /返回 200 且响应包含 Welcome to Knative and Elixir。环境准备在本地安装 Elixir 与 Phoenix要开发、构建、运行并打包 Elixir Web 应用首先需要在本机配置好工具链。按照 Phoenix 官方安装指南安装以下组件即可Elixir 与 Erlang/OTPPhoenix 运行的基础运行时HexElixir 的包管理器用于mix deps.get拉取依赖Node.js 与 npm用于编译前端资源本示例通过 brunch 打包 JS/CSS。示例工程在 mix.exs 中声明了依赖版本Phoenix~ 1.3.2、Cowboy~ 1.0HTTP 服务器、Distillery~ 1.5OTP 发布工具、Gettext~ 0.11等Elixir 版本要求为~ 1.4。需要说明的是该示例是 Phoenix 1.3 时代的工程结构若使用更新版本的 Phoenix目录布局与发布命令会有所差异但核心思路一致。本地运行三步启动 Phoenix 服务在项目根目录即仓库中的 helloworld-elixir 目录依次执行# 1. 安装 Elixir 依赖 mix deps.get # 2. 安装 Node.js 依赖进入 assets 子目录 cd assets npm install # 3. 启动 Phoenix 服务 mix phx.server启动成功后浏览器访问localhost:4000即可看到页面。开发端口由 config/dev.exs 配置为http: [port: 4000]并开启debug_errors、code_reloader以及 brunch 的资源监听重编译。从零重建示例生成 Phoenix 项目如果你希望从空白项目一步步复现这个示例可以按下面的流程操作。1. 生成新项目mix phoenix.new helloelixir当命令行询问Fetch and install dependencies? [Yn]时输入y确认拉取依赖。随后根据输出提示进入项目目录并用mix phoenix.server启动本地服务验证脚手架是否正常。2. 让生产环境监听 8080 端口Knative Serving 默认期望容器在 8080 端口提供 HTTP 服务。仓库中的生产配置 config/prod.exs 已经做了对应设置config :hello, HelloWeb.Endpoint, load_from_system_env: false, http: [port: 8080], check_origin: false, server: true, root: ., cache_static_manifest: priv/static/cache_manifest.json其中server: true确保在生产发布启动时拉起 HTTP 服务check_origin: false关闭来源校验以允许跨域请求cache_static_manifest配合mix phx.digest生成的资源指纹清单提供静态文件缓存。作为对照endpoint.ex 中的init/2回调保留了load_from_system_env为 true 时从PORT环境变量动态读取端口的逻辑——本示例生产配置将其置为 false固定使用 8080。3. 编写 Dockerfile 打包应用在项目目录下创建 Dockerfile其采用多阶段构建把编译环境与运行环境分离# 阶段一构建环境elixir:1.6.6-alpine FROM elixir:1.6.6-alpine ARG APP_NAMEhello ARG PHOENIX_SUBDIR. ENV MIX_ENVprod REPLACE_OS_VARStrue TERMxterm WORKDIR /opt/app # 安装 nodejs、rebar、hex RUN apk update \ apk --no-cache --update add nodejs nodejs-npm \ mix local.rebar --force \ mix local.hex --force COPY . . # 下载并编译依赖随后编译 Web 应用 RUN mix do deps.get, deps.compile, compile RUN cd ${PHOENIX_SUBDIR}/assets \ npm install \ ./node_modules/brunch/bin/brunch build -p \ cd .. \ mix phx.digest # 用 Distillery 生成生产发布包 RUN mix release --envprod --verbose \ mv _build/prod/rel/${APP_NAME} /opt/release \ mv /opt/release/bin/${APP_NAME} /opt/release/bin/start_server # 阶段二精简运行环境 FROM alpine:latest RUN apk update apk --no-cache --update add bash openssl-dev ca-certificates # 创建非 root 用户提升安全性 RUN addgroup -g 1000 appuser \ adduser -S -u 1000 -G appuser appuser # 预创建 Erlang 运行时所需临时目录并授权 RUN mkdir -p /opt/app/var RUN chown appuser /opt/app/var USER appuser ENV MIX_ENVprod REPLACE_OS_VARStrue WORKDIR /opt/app COPY --from0 /opt/release . ENV RUNNER_LOG_DIR /var/log # 以前台方式启动发布包 CMD [/opt/app/bin/start_server, foreground, boot_var/tmp]这段 Dockerfile 的关键点可以结合仓库配置逐条展开构建阶段先补齐nodejs、nodejs-npm、rebar、hex再执行mix do deps.get, deps.compile, compile完成依赖与源码编译前端资源由 assets/brunch-config.js 驱动 brunch 编译JS 合并输出到js/app.jsCSS 合并输出到css/app.css产物发布到../priv/staticpaths.public配置随后mix phx.digest对静态资源做内容指纹化生成priv/static/cache_manifest.json发布包由 Distillery 生成rel/config.exs 定义了:prod环境include_erts: true随包携带 Erlang 运行时因此最终镜像无需再装 Erlang与名为:hello的 release版本取自mix.exs的version: 0.0.1运行阶段使用alpine:latest精简镜像仅保留bash、openssl-dev、ca-certificates并通过USER appuser以非 root 用户运行符合容器安全最佳实践REPLACE_OS_VARStrue允许在启动时用环境变量替换sys.config中的占位符这正是 Knative 注入配置的手段之一。4. 编写 Knative Service 定义创建service.yaml内容如下请将{username}替换为你自己的 Docker Hub 用户名apiVersion: serving.knative.dev/v1 kind: Service metadata: name: helloworld-elixir namespace: default spec: template: spec: containers: - image: docker.io/{username}/helloworld-elixir env: - name: TARGET value: elixir Sample v1这个定义与仓库中的 service.yaml 完全一致。它的核心作用有两点通过image指定容器镜像Knative 会据此拉起 Pod通过env注入TARGETelixir Sample v1环境变量——这正是应用首页$TARGET一行的数据来源你可以随意修改它的值来验证环境变量的传递。构建并部署到 Knative仓库目录下的示例本身已可直接构建部署你也可以使用上述步骤自建版本。1. 生成生产密钥 secret_key_basePhoenix 应用在生产环境使用一个密钥文件config/prod.secret.exs它默认不纳入版本控制。仓库提供了模板 config/prod.secret.exs.sample其中secret_key_base值为占位符SECRETKEYBASE。部署前必须生成随机密钥并替换SECRET_KEY_BASE$(elixir -e :crypto.strong_rand_bytes(48) | Base.encode64 | IO.puts) sed s|SECRETKEYBASE|$SECRET_KEY_BASE| config/prod.secret.exs.sample config/prod.secret.exs命令先用 Elixir 的:crypto.strong_rand_bytes/1生成 48 字节强随机数再Base.encode64编码为密钥字符串最后用sed将模板中的占位符替换并写入正式配置文件。该文件会被 config/prod.exs 末尾的import_config prod.secret.exs引入。2. 构建并推送多架构镜像使用 Docker Buildx 一次性构建并推送linux/arm64与linux/amd64双架构镜像# 在本地构建并推送镜像到 Docker Hub docker buildx build --platform linux/arm64,linux/amd64 -t {username}/helloworld-elixir --push .多架构构建可以让同一镜像同时适配 x86_64 与 ARM 集群节点--push在构建完成后直接推送到镜像仓库。3. 应用 Service 配置构建并推送完成后确认service.yaml中的镜像值与你刚才构建的镜像一致然后使用kubectl应用到集群kubectl apply --filename service.yamlService 创建成功后Knative Serving 会自动完成以下工作为该版本应用创建一个不可变的 Revision修订版本进行网络编程创建 Route、Ingress、Service 与负载均衡器把流量导向应用根据流量自动扩缩容 Pod——包括缩容到0 个活跃 Pod这也是 Serverless 按需计费的核心机制。4. 获取服务 URL执行以下命令查看服务对外访问地址kubectl get ksvc helloworld-elixir --outputcustom-columnsNAME:.metadata.name,URL:.status.url NAME URL helloworld-elixir http://helloworld-elixir.default.1.2.3.4.sslip.io示例输出中的域名基于sslip.io通配 DNS 生成实际地址由你的集群域名配置决定请以你查询到的输出为准。5. 请求验证将上一步返回的地址替换进下面的命令向应用发起请求curl http://helloworld-elixir.default.1.2.3.4.sslip.io应用会返回完整 HTML 页面。仓库示例部署后的典型输出如下节选关键部分!DOCTYPE html html langen head meta charsetutf-8 titleHello Knative/title link relstylesheet typetext/css href/css/app-833cc7e8eeed7a7953c5a02e28130dbd.css?vsnd /head body main rolemain div classjumbotron h2Welcome to Knative and Elixir/h2 p$TARGET elixir Sample v1/p /div h3Environment/h3 ul liMIX_ENV prod/li liTARGET elixir Sample v1/li liPORT 8080/li liHOSTNAME helloworld-elixir-00001-deployment-84f68946b4-76hcv/li liKUBERNETES_SERVICE_HOST 10.35.240.1/li liHELLOWORLD_ELIXIR_SERVICE_HOST 10.35.253.90/li li.../li /ul /main /body /html深入原理环境变量是如何到达页面的这个示例最值得研究的一点是环境变量从 Kubernetes 到浏览器页面的完整链路注入service.yaml中的env字段把TARGET写入 Knative Service 的容器定义Kubernetes 在创建 Pod 时将其注入容器同时 K8s 还会自动注入KUBERNETES_SERVICE_HOST、HELLOWORLD_ELIXIR_SERVICE_HOST等服务发现变量这解释了页面输出里大量xxx_SERVICE_HOST条目的来源读取page_controller.ex 调用System.get_env()读取容器进程的完整环境变量字典并用Map.get(env, TARGET)取出目标值渲染模板 index.html.eex 把字典按键排序后逐行输出监听端口生产配置固定 8080恰好是 Knative 的默认容器端口因此 Knative 探活与流量转发无需额外配置即可命中应用。从部署输出还能观察到 Distillery 发布包的内部结构ERTS_VSN 9.3.2、REL_VSN 0.0.1、REL_NAME hello等变量印证了发布包由 Erlang 运行时随elixir:1.6.6-alpine基础镜像的 OTP 20与rel/config.exs中release :hello版本 0.0.1生成REPLACE_OS_VARS true则确认了镜像内启用了环境变量替换机制。测试验证保障应用行为仓库为示例提供了基于 ExUnit 的控制器测试 page_controller_test.exsdefmodule HelloWeb.PageControllerTest do use HelloWeb.ConnCase test GET /, %{conn: conn} do conn get conn, / assert html_response(conn, 200) ~ Welcome to Knative and Elixir end end测试通过HelloWeb.ConnCase见 conn_case.ex构建连接断言首页返回 200 且包含欢迎语。在MIX_ENVtest下运行mix test即可验证。这为镜像构建前的本地回归提供了保障。清理部署验证完成后如需从集群移除示例应用删除 Service 记录即可kubectl delete --filename service.yaml删除后Knative 会随之清理对应的 Revision、Route 以及自动创建的 Service 与负载均衡资源。参考与延伸阅读示例主文档code-samples/community/serving/helloworld-elixir/index.md示例 READMEcode-samples/community/serving/helloworld-elixir/README.md完整工程源码helloworld-elixir 目录社区代码示例总览code-samples/community/serving/README.md 与 code-samples/README.md如果你希望尝试其他语言的 Serverless 部署仓库中还有 Java、Go、Python、Node.js、Rust 等多个社区的 Hello World 示例可供对照学习。赞分享文档教程云原生【免费下载链接】docsUser documentation for Knative components.项目地址https://gitcode.com/gh_mirrors/docs1/docs点击查看免费下载相关推荐用 Clojure 编写并部署 Knative Serving Hello World 服务用 Clojure 编写并部署 Knative Serving Hello World 服务 导读 本文基于 Knative 文档仓库中的社区示例 hellow文档教程云原生用 Deno 编写 Hello World 应用并部署到 Knative Serving社区示例完整实战用 Deno 编写 Hello World 应用并部署到 Knative Serving社区示例完整实战 本文基于 Knative 官方文档仓库中的社区示例文档教程云原生使用 Deno 构建并部署 Knative Serving 无服务器应用helloworld-deno 完整实践指南使用 Deno 构建并部署 Knative Serving 无服务器应用helloworld deno 完整实践指南 本指南以 Knative 官方社区示例文档教程云原生上一篇lsix终端兼容性支持Sixel图形的终端完全清单下一篇CANN/cannbot-skills错误模式参考创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑