This commit is contained in:
anlicheng 2026-05-11 22:42:00 +08:00
parent e88ad2078f
commit 069e99dc16
18 changed files with 107 additions and 40 deletions

View File

@ -44,10 +44,13 @@ WebSocket server
- `service_model`DETS 服务状态表。
- `efka_subscription`:本地 topic 订阅中心。
- `efka_client`:连接上游 TLS server 的状态机。
`docker` application 启动的子进程:
- `docker_task_reporter`:部署任务事件缓冲和转发。
- `docker_deploy_manager`:部署任务管理器。
`docker_events` 代码存在,但在 `efka_sup` 中被注释掉了,目前默认不会启动。
`docker_events` 代码存在`apps/docker`,但目前默认不会启动。
## 3. 两条通信链路
@ -180,7 +183,7 @@ topic 匹配规则:
部署操作:
1. `docker_container_service` 收到 `deploy` 后调用 `docker_deploy_manager:deploy(TaskId, Params)`
2. `docker_deploy_manager` 根据 `root_dir` 和参数里的 `container_name/container_dir` 确保容器目录存在。
2. `docker_deploy_manager` 根据 `docker.root_dir` 和参数里的 `container_name/container_dir` 确保容器目录存在。
3. 它启动一个独立 `docker_deployer` 进程,并 monitor 该部署进程。
4. `docker_deployer` 执行实际部署步骤。
5. 部署过程事件写入 `docker_task_reporter`
@ -261,7 +264,7 @@ topic 匹配规则:
关键配置来自 `config/sys.config`
- `root_dir`:容器相关目录根路径。
- `docker.root_dir`:容器相关目录根路径。
- `dets_dir`DETS 文件目录。
- `websocket_server`:本地 WebSocket 监听配置。
- `tls_server_address`:上游 TLS server 地址。

View File

@ -0,0 +1,18 @@
{application, docker,
[{description, "Docker integration application"},
{vsn, "0.1.0"},
{registered, []},
{mod, {docker_app, []}},
{applications,
[
gun,
kernel,
stdlib
]},
{env, [
{root_dir, "/usr/local/code/efka"}
]},
{modules, []},
{licenses, ["Apache-2.0"]},
{links, []}
]}.

View File

@ -0,0 +1,18 @@
%%%-------------------------------------------------------------------
%% @doc Docker application entry point.
%% @end
%%%-------------------------------------------------------------------
-module(docker_app).
-behaviour(application).
-export([start/2, stop/1]).
-spec start(term(), term()) -> {ok, pid()} | {error, term()}.
start(_StartType, _StartArgs) ->
docker_sup:start_link().
-spec stop(term()) -> ok.
stop(_State) ->
ok.

View File

@ -43,7 +43,7 @@ deploy(TaskId, Params) when is_integer(TaskId), is_map(Params) ->
-spec init(list()) -> {ok, #state{}}.
init([]) ->
erlang:process_flag(trap_exit, true),
{ok, RootDir} = application:get_env(efka, root_dir),
{ok, RootDir} = docker_helper:root_dir(),
{ok, #state{root_dir = RootDir}}.
-spec handle_call(term(), {pid(), term()}, #state{}) -> {reply, term(), #state{}}.

View File

@ -10,9 +10,19 @@
-author("anlicheng").
%% API
-export([root_dir/0]).
-export([ensure_container_dir/2, ensure_container_dir/3, get_container_dir/2, get_config_file/1]).
-export([update_container_config/2]).
-spec root_dir() -> {ok, string()} | undefined.
root_dir() ->
case application:get_env(docker, root_dir) of
{ok, RootDir} ->
{ok, RootDir};
undefined ->
application:get_env(efka, root_dir)
end.
-spec ensure_container_dir(RootDir :: string(), ContainerName :: binary()) -> {ok, ServerRootDir :: string()}.
ensure_container_dir(RootDir, ContainerName) when is_list(RootDir), is_binary(ContainerName) ->
ensure_container_dir(RootDir, ContainerName, <<>>).
@ -52,7 +62,7 @@ get_container_dir(RootDir, ContainerName) when is_list(RootDir), is_binary(Conta
-spec update_container_config(binary(), binary()) -> ok | {error, binary()}.
update_container_config(ContainerName, Config) when is_binary(ContainerName), is_binary(Config) ->
{ok, RootDir} = application:get_env(efka, root_dir),
{ok, RootDir} = root_dir(),
case get_container_dir(RootDir, ContainerName) of
{ok, ContainerDir} ->
ConfigFile = get_config_file(ContainerDir),

View File

@ -0,0 +1,42 @@
%%%-------------------------------------------------------------------
%% @doc Docker top level supervisor.
%% @end
%%%-------------------------------------------------------------------
-module(docker_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
-define(SERVER, ?MODULE).
-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
-spec init(list()) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
ChildSpecs = [
#{
id => docker_task_reporter,
start => {docker_task_reporter, start_link, []},
restart => permanent,
shutdown => 2000,
type => worker,
modules => [docker_task_reporter]
},
#{
id => docker_deploy_manager,
start => {docker_deploy_manager, start_link, []},
restart => permanent,
shutdown => 2000,
type => worker,
modules => [docker_deploy_manager]
}
],
{ok, {SupFlags, ChildSpecs}}.

View File

@ -6,10 +6,10 @@
{applications,
[
sync,
docker,
cowboy,
ranch,
crypto,
gun,
cowlib,
inets,
ssl,

View File

@ -48,15 +48,6 @@ init([]) ->
modules => ['efka_service_sup']
},
%#{
% id => 'docker_events',
% start => {'docker_events', start_link, []},
% restart => permanent,
% shutdown => 2000,
% type => worker,
% modules => ['docker_events']
%},
#{
id => service_model,
start => {service_model, start_link, []},
@ -91,24 +82,6 @@ init([]) ->
shutdown => 2000,
type => worker,
modules => ['efka_heartbeat']
},
#{
id => 'docker_task_reporter',
start => {'docker_task_reporter', start_link, []},
restart => permanent,
shutdown => 2000,
type => worker,
modules => ['docker_task_reporter']
},
#{
id => 'docker_deploy_manager',
start => {'docker_deploy_manager', start_link, []},
restart => permanent,
shutdown => 2000,
type => worker,
modules => ['docker_deploy_manager']
}
],

View File

@ -1,6 +1,5 @@
[
{efka, [
{root_dir, "/usr/local/code/efka"},
{dets_dir, "/usr/local/code/tmp/dets/"},
{websocket_server, [
@ -27,6 +26,10 @@
]},
{docker, [
{root_dir, "/usr/local/code/efka"}
]},
%% 系统日志配置,使用 OTP logger
{kernel, [
%% 设置 Logger 的 primary log level

View File

@ -5,10 +5,10 @@
对应代码:
- command 接收入口:[src/transport/efka_client.erl](/usr/local/code/cloudkit/efka/apps/efka/src/transport/efka_client.erl:177)
- 部署任务管理:[src/docker/docker_deploy_manager.erl](/usr/local/code/cloudkit/efka/apps/efka/src/docker/docker_deploy_manager.erl:36)
- 部署执行:[src/docker/docker_deployer.erl](/usr/local/code/cloudkit/efka/apps/efka/src/docker/docker_deployer.erl:39)
- Docker JSON 构造:[src/docker/docker_container_builder.erl](/usr/local/code/cloudkit/efka/apps/efka/src/docker/docker_container_builder.erl:14)
- Docker API 调用:[src/docker/docker_commands.erl](/usr/local/code/cloudkit/efka/apps/efka/src/docker/docker_commands.erl:36)
- 部署任务管理:[docker_deploy_manager.erl](/usr/local/code/cloudkit/efka/apps/docker/src/docker_deploy_manager.erl:36)
- 部署执行:[docker_deployer.erl](/usr/local/code/cloudkit/efka/apps/docker/src/docker_deployer.erl:39)
- Docker JSON 构造:[docker_container_builder.erl](/usr/local/code/cloudkit/efka/apps/docker/src/docker_container_builder.erl:14)
- Docker API 调用:[docker_commands.erl](/usr/local/code/cloudkit/efka/apps/docker/src/docker_commands.erl:36)
## 1. 协议入口
@ -214,7 +214,7 @@ docker_helper:update_container_config(ContainerNameOrId, iolist_to_binary(Config
`docker_deploy_manager` 会根据 `container_name` 按系统默认规则确保容器目录存在。目录固定为:
```text
efka.root_dir/container_name/
docker.root_dir/container_name/
```
即使旧客户端在 `params` 中携带 `container_dir`,当前 deploy 流程也会忽略它,避免 HTTP 调用方控制 efka 主机上的写入目录。
@ -790,7 +790,7 @@ efka 自动补丁后输出:
deploy action 的执行流程:
1. 根据 `container_name``efka.root_dir` 确保默认容器目录存在。
1. 根据 `container_name``docker.root_dir` 确保默认容器目录存在。
2. 启动独立部署进程。
3. 部署进程上报任务事件流。
4. 规范化镜像名:如果镜像最后一段没有 tag则补 `:latest`