diff --git a/apps/efka/src/docker/efka_docker_command.erl b/apps/efka/src/docker/efka_docker_command.erl index 18a811d..40b140f 100644 --- a/apps/efka/src/docker/efka_docker_command.erl +++ b/apps/efka/src/docker/efka_docker_command.erl @@ -11,7 +11,7 @@ %% API -export([pull_image/1, check_image_exist/1]). --export([create_container/2]). +-export([create_container/3, check_container_exist/1]). -spec pull_image(Image :: binary()) -> ok | {error, Reason :: any()}. pull_image(Image) when is_binary(Image) -> @@ -34,8 +34,8 @@ pull_image(Image) when is_binary(Image) -> {error, <<"exec command startup failed">>} end. --spec create_container(ContainerDir :: string(), Config :: map()) -> ok | {error, Reason :: any()}. -create_container(ContainerDir, Config) when is_map(Config) -> +-spec create_container(ContainerName :: binary(), ContainerDir :: string(), Config :: map()) -> ok | {error, Reason :: any()}. +create_container(ContainerName, ContainerDir, Config) when is_binary(ContainerName), is_list(ContainerDir), is_map(Config) -> Image = maps:get(<<"image">>, Config), Cmd = maps:get(<<"command">>, Config, []), @@ -49,7 +49,7 @@ create_container(ContainerDir, Config) when is_map(Config) -> %% todo 重定向错误流 {stderr_to_stdout, true} PortSettings = [stream, exit_status, use_stdio, binary], - ExecCmd = "docker create " ++ binary_to_list(CreateArgs), + ExecCmd = "docker create --name " ++ binary_to_list(ContainerName) ++ " " ++ binary_to_list(CreateArgs), lager:debug("create_container cmd : ~p", [ExecCmd]), case catch erlang:open_port({spawn, ExecCmd}, PortSettings) of Port when is_port(Port) -> @@ -85,6 +85,23 @@ check_image_exist(Image) when is_binary(Image) -> false end. +-spec check_container_exist(ContainerName :: binary()) -> boolean(). +check_container_exist(ContainerName) when is_binary(ContainerName) -> + PortSettings = [stream, exit_status, use_stdio, binary], + ExecCmd = "docker inspect --type=container " ++ binary_to_list(ContainerName) ++ " >/dev/null 2>&1", + lager:debug("check_container_exist cmd : ~p", [ExecCmd]), + case catch erlang:open_port({spawn, ExecCmd}, PortSettings) of + Port when is_port(Port) -> + case gather_output(Port) of + {0, _} -> + true; + {_ExitCode, _Error} -> + false + end; + _Error -> + false + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% helper methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -120,7 +137,6 @@ starts_with(Binary, Prefix) when is_binary(Binary), is_binary(Prefix) -> %% 构建所有参数 build_options(Config) -> lists:flatten([ - build_name(Config), build_entrypoint(Config), build_ports(Config), build_expose(Config), @@ -145,12 +161,6 @@ build_options(Config) -> build_healthcheck(Config) ]). -build_name(Config) -> - case maps:get(<<"container_name">>, Config, undefined) of - undefined -> []; - Name -> [<<"--name">>, Name] - end. - build_entrypoint(Config) -> case maps:get(<<"entrypoint">>, Config, []) of [] -> []; @@ -170,7 +180,7 @@ build_volumes(Config) -> lists:map(fun(V) -> [<<"-v">>, V] end, Vols). build_env(Config) -> - Envs = maps:get(<<"environment">>, Config, []), + Envs = maps:get(<<"envs">>, Config, []), lists:map(fun(E) -> [<<"-e">>, E] end, Envs). build_env_file(Config) -> diff --git a/apps/efka/src/efka_inetd_task.erl b/apps/efka/src/efka_inetd_task.erl index 8ba5e26..cb9792d 100644 --- a/apps/efka/src/efka_inetd_task.erl +++ b/apps/efka/src/efka_inetd_task.erl @@ -25,8 +25,7 @@ -record(state, { root_dir :: string(), task_id :: integer(), - image_url :: binary(), - args = [] :: list() + config = #{} }). test() -> @@ -35,7 +34,7 @@ test() -> <<"container_name">> => <<"my_nginx">>, <<"command">> => [<<"nginx">>,<<"-g">>,<<"daemon off;">>], <<"entrypoint">> => [<<"/docker-entrypoint.sh">>], - <<"environment">> => [<<"ENV1=val1">>, <<"ENV2=val2">>], + <<"envs">> => [<<"ENV1=val1">>, <<"ENV2=val2">>], <<"env_file">> => [<<"./env.list">>], <<"ports">> => [<<"8080:80">>, <<"443:443">>], <<"expose">> => [<<"80">>, <<"443">>], @@ -96,8 +95,8 @@ start_link(TaskId, RootDir, Config) when is_integer(TaskId), is_list(RootDir), i -spec(init(Args :: term()) -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). -init([TaskId, RootDir, ImageUrl, Args]) -> - {ok, #state{task_id = TaskId, root_dir = RootDir, image_url = ImageUrl, args = Args}}. +init([TaskId, RootDir, Config]) -> + {ok, #state{task_id = TaskId, root_dir = RootDir, config = Config}}. %% @private %% @doc Handling call messages @@ -118,8 +117,8 @@ handle_call(_Request, _From, State = #state{}) -> {noreply, NewState :: #state{}} | {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), NewState :: #state{}}). -handle_cast(deploy, State = #state{task_id = TaskId, root_dir = RootDir, image_url = ImageUrl, args = Args}) -> - do_deploy(TaskId, RootDir, ImageUrl, Args), +handle_cast(deploy, State = #state{task_id = TaskId, root_dir = RootDir, config = Config}) -> + do_deploy(TaskId, RootDir, Config), {stop, normal, State}; handle_cast(_Request, State) -> {stop, normal, State}. @@ -180,11 +179,16 @@ do_deploy(TaskId, RootDir, Config) when is_integer(TaskId), is_list(RootDir), is maybe_create_env_file(ContainerDir, maps:get(<<"envs">>, Config, [])), %% 创建镜像, 并预留配置文件的绑定位置: "/etc/容器名称/" - case efka_docker_command:create_container(ContainerDir, Config) of - ok -> - ok; - {error, Reason} -> - {error, Reason} + case efka_docker_command:check_container_exist(ContainerName) of + true -> + {error, <<"container exist">>}; + false -> + case efka_docker_command:create_container(ContainerName, ContainerDir, Config) of + ok -> + ok; + {error, Reason} -> + {error, Reason} + end end; {error, Reason} -> {error, Reason} @@ -202,6 +206,7 @@ try_pull_image(Image) when is_binary(Image) -> maybe_create_env_file(_ContainerDir, []) -> ok; maybe_create_env_file(ContainerDir, Envs) when is_list(Envs)-> + lager:debug("envs: ~p", [Envs]), TargetFile = ContainerDir ++ "env", {ok, IoDevice} = file:open(TargetFile, [write, binary]), lists:foreach(fun(Env) -> file:write(IoDevice, <>) end, Envs),