fix docker client

This commit is contained in:
anlicheng 2026-04-23 17:23:54 +08:00
parent 50394128c7
commit 660ab164dd
4 changed files with 58 additions and 50 deletions

View File

@ -12,7 +12,7 @@
-behaviour(gen_server). -behaviour(gen_server).
%% API %% API
-export([request/4, start_stream/5, stream_request/5]). -export([request/4, start_stream/5]).
%% gen_server callbacks %% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
@ -73,21 +73,6 @@ start_stream(Owner, Method, Path, Body, Headers)
{error, Reason} {error, Reason}
end. end.
%% Backward-compatible wrapper for existing callers. New stream users should prefer start_stream/5.
-spec stream_request(Callback :: fun((term()) -> any()), Method :: string(), Path :: string(), Body :: binary(), Headers :: list()) ->
ok | {error, Reason :: any()}.
stream_request(Callback, Method, Path, Body, Headers)
when is_function(Callback, 1), is_list(Method), is_list(Path), is_binary(Body), is_list(Headers) ->
case start_stream(self(), Method, Path, Body, Headers) of
{ok, Ref, Pid} ->
MRef = erlang:monitor(process, Pid),
await_stream(Ref, Callback, Pid, MRef);
{error, Reason0} ->
Reason = format_error(Reason0),
Callback({error, Reason}),
{error, Reason}
end.
%%%=================================================================== %%%===================================================================
%%% gen_server callbacks %%% gen_server callbacks
%%%=================================================================== %%%===================================================================
@ -307,27 +292,6 @@ receive_stream_error_body(State, ConnPid, StreamRef, Status, Acc) ->
{error, Reason} {error, Reason}
end. end.
-spec await_stream(reference(), fun((term()) -> any()), pid(), reference()) -> ok | {error, binary()}.
await_stream(Ref, Callback, Pid, MRef) ->
receive
{docker_client, Ref, {response, _Status, _Headers}} ->
await_stream(Ref, Callback, Pid, MRef);
{docker_client, Ref, {data, Data}} ->
Callback({message, Data}),
await_stream(Ref, Callback, Pid, MRef);
{docker_client, Ref, done} ->
erlang:demonitor(MRef, [flush]),
ok;
{docker_client, Ref, {error, Reason}} ->
erlang:demonitor(MRef, [flush]),
Callback({error, Reason}),
{error, Reason};
{'DOWN', MRef, process, Pid, Reason0} ->
Reason = format_error({client_down, Reason0}),
Callback({error, Reason}),
{error, Reason}
end.
-spec open_connection() -> {ok, pid()} | {error, any()}. -spec open_connection() -> {ok, pid()} | {error, any()}.
open_connection() -> open_connection() ->
case gun:open_unix(?DOCKER_SOCKET, #{}) of case gun:open_unix(?DOCKER_SOCKET, #{}) of

View File

@ -11,15 +11,15 @@
-include("message_pb.hrl"). -include("message_pb.hrl").
%% API %% API
-export([pull_image/2, check_image_exist/1]). -export([pull_image/1, check_image_exist/1]).
-export([create_container/2, check_container_exist/1, is_container_running/1, -export([create_container/2, check_container_exist/1, is_container_running/1,
start_container/1, stop_container/1, stop_container/2, remove_container/1, remove_container/3, kill_container/1, kill_container/2, start_container/1, stop_container/1, stop_container/2, remove_container/1, remove_container/3, kill_container/1, kill_container/2,
get_containers/0]). get_containers/0]).
-spec pull_image(Image :: binary(), Callback :: fun((Msg :: any()) -> no_return())) -> ok | {error, Reason :: any()}. -spec pull_image(Image :: binary()) -> {ok, Ref :: reference(), Pid :: pid()} | {error, Reason :: any()}.
pull_image(Image, Callback) when is_binary(Image), is_function(Callback, 1) -> pull_image(Image) when is_binary(Image) ->
Url = lists:flatten(io_lib:format("/images/create?fromImage=~s", [binary_to_list(Image)])), Url = lists:flatten(io_lib:format("/images/create?fromImage=~s", [binary_to_list(Image)])),
docker_client:stream_request(Callback, "POST", Url, <<>>, []). docker_client:start_stream(self(), "POST", Url, <<>>, []).
-spec check_image_exist(Image :: binary()) -> boolean(). -spec check_image_exist(Image :: binary()) -> boolean().
check_image_exist(Image) when is_binary(Image) -> check_image_exist(Image) when is_binary(Image) ->

View File

@ -125,14 +125,9 @@ ensure_image_ready(TaskId, Image0) when is_integer(TaskId), is_binary(Image0) ->
Image = normalize_image(Image0), Image = normalize_image(Image0),
report_task_event(TaskId, <<"info">>, <<"使用镜像:"/utf8, Image/binary>>), report_task_event(TaskId, <<"info">>, <<"使用镜像:"/utf8, Image/binary>>),
report_task_event(TaskId, <<"info">>, <<"开始拉取镜像:"/utf8, Image/binary>>), report_task_event(TaskId, <<"info">>, <<"开始拉取镜像:"/utf8, Image/binary>>),
CB = fun case docker_commands:pull_image(Image) of
({message, M}) -> {ok, Ref, Pid} ->
report_task_event(TaskId, <<"info">>, M); await_pull_image(TaskId, Ref, Pid),
({error, Error}) ->
report_task_event(TaskId, <<"error">>, Error)
end,
case docker_commands:pull_image(Image, CB) of
ok ->
{ok, Image}; {ok, Image};
{error, Reason} when is_binary(Reason) -> {error, Reason} when is_binary(Reason) ->
throw({deploy_error, <<"镜像拉取失败: "/utf8, Reason/binary>>}); throw({deploy_error, <<"镜像拉取失败: "/utf8, Reason/binary>>});
@ -141,6 +136,31 @@ ensure_image_ready(TaskId, Image0) when is_integer(TaskId), is_binary(Image0) ->
throw({deploy_error, Error}) throw({deploy_error, Error})
end. end.
-spec await_pull_image(TaskId :: integer(), Ref :: reference(), Pid :: pid()) -> ok.
await_pull_image(TaskId, Ref, Pid) when is_integer(TaskId), is_reference(Ref), is_pid(Pid) ->
MRef = erlang:monitor(process, Pid),
await_pull_image(TaskId, Ref, Pid, MRef).
-spec await_pull_image(TaskId :: integer(), Ref :: reference(), Pid :: pid(), MRef :: reference()) -> ok.
await_pull_image(TaskId, Ref, Pid, MRef) ->
receive
{docker_client, Ref, {response, _Status, _Headers}} ->
await_pull_image(TaskId, Ref, Pid, MRef);
{docker_client, Ref, {data, Data}} ->
report_task_event(TaskId, <<"info">>, Data),
await_pull_image(TaskId, Ref, Pid, MRef);
{docker_client, Ref, done} ->
erlang:demonitor(MRef, [flush]),
ok;
{docker_client, Ref, {error, Reason}} ->
erlang:demonitor(MRef, [flush]),
report_task_event(TaskId, <<"error">>, Reason),
throw({deploy_error, <<"镜像拉取失败: "/utf8, Reason/binary>>});
{'DOWN', MRef, process, Pid, Reason0} ->
Reason = iolist_to_binary(io_lib:format("~p", [Reason0])),
throw({deploy_error, <<"镜像拉取失败: "/utf8, Reason/binary>>})
end.
-spec create_container_and_config(TaskId :: integer(), ContainerDir :: string(), Params :: message_pb:'ContainerDeployParams'()) -> -spec create_container_and_config(TaskId :: integer(), ContainerDir :: string(), Params :: message_pb:'ContainerDeployParams'()) ->
{ok, binary()}. {ok, binary()}.
create_container_and_config(TaskId, ContainerDir, Params) create_container_and_config(TaskId, ContainerDir, Params)

View File

@ -67,7 +67,31 @@ test_all() ->
-spec test_pull() -> ok. -spec test_pull() -> ok.
test_pull() -> test_pull() ->
ok = docker_commands:pull_image(?TEST_IMAGE, fun(Msg) -> logger:debug("msg is: ~p", [Msg]) end). {ok, Ref, Pid} = docker_commands:pull_image(?TEST_IMAGE),
await_pull(Ref, Pid).
-spec await_pull(reference(), pid()) -> ok.
await_pull(Ref, Pid) when is_reference(Ref), is_pid(Pid) ->
MRef = erlang:monitor(process, Pid),
await_pull(Ref, Pid, MRef).
-spec await_pull(reference(), pid(), reference()) -> ok.
await_pull(Ref, Pid, MRef) ->
receive
{docker_client, Ref, {response, _Status, _Headers}} ->
await_pull(Ref, Pid, MRef);
{docker_client, Ref, {data, Data}} ->
logger:debug("msg is: ~p", [Data]),
await_pull(Ref, Pid, MRef);
{docker_client, Ref, done} ->
erlang:demonitor(MRef, [flush]),
ok;
{docker_client, Ref, {error, Reason}} ->
erlang:demonitor(MRef, [flush]),
error({pull_failed, Reason});
{'DOWN', MRef, process, Pid, Reason} ->
error({pull_client_down, Reason})
end.
-spec test_check_image_exist() -> ok. -spec test_check_image_exist() -> ok.
test_check_image_exist() -> test_check_image_exist() ->