diff --git a/apps/efka/src/docker/docker_commands.erl b/apps/efka/src/docker/docker_commands.erl index 202a1ee..16b9fe6 100644 --- a/apps/efka/src/docker/docker_commands.erl +++ b/apps/efka/src/docker/docker_commands.erl @@ -11,99 +11,7 @@ %% API -export([pull_image/2, check_image_exist/1]). --export([create_container/3, check_container_exist/1, is_container_running/1, start_container/1, stop_container/1]). --export([test/0, test_create_container/0, test1/0]). - -test() -> - Image = <<"docker.1ms.run/library/nginx:latest">>, - pull_image(Image, fun(Msg) -> lager:debug("msg is: ~p", [Msg]) end). - -test1() -> - Id = <<"redpanda-console">>, - StopRes = stop_container(Id), - lager:debug("stop res: ~p", [StopRes]), - StartRes = start_container(Id), - lager:debug("start res: ~p", [StartRes]). - -test_create_container() -> - M = #{ - <<"image">> => <<"docker.1ms.run/library/nginx:latest">>, - <<"container_name">> => <<"my_nginx_new1">>, - <<"command">> => [ - <<"nginx">>, - <<"-g">>, - <<"daemon off;">> - ], - <<"entrypoint">> => [ - <<"/docker-entrypoint.sh">> - ], - <<"envs">> => [ - <<"ENV1=val1">>, - <<"ENV2=val2">> - ], - <<"env_file">> => [ - <<"./env.list">> - ], - <<"ports">> => [ - <<"8080:80">>, - <<"443:443">> - ], - <<"expose">> => [ - <<"80">>, - <<"443">> - ], - <<"volumes">> => [ - <<"/host/data:/data">>, - <<"/host/log:/var/log">> - ], - <<"networks">> => [ - <<"mynet">> - ], - <<"labels">> => #{ - <<"role">> => <<"web">>, - <<"env">> => <<"prod">> - }, - <<"restart">> => <<"always">>, - <<"user">> => <<"www-data">>, - <<"working_dir">> => <<"/app">>, - <<"hostname">> => <<"myhost">>, - <<"privileged">> => true, - <<"cap_add">> => [ - <<"NET_ADMIN">> - ], - <<"cap_drop">> => [ - <<"MKNOD">> - ], - <<"devices">> => [ - <<"/dev/snd:/dev/snd">> - ], - <<"mem_limit">> => <<"512m">>, - <<"mem_reservation">> => <<"256m">>, - <<"cpu_shares">> => 512, - <<"cpus">> => 1.5, - <<"ulimits">> => #{ - <<"nofile">> => <<"1024:2048">> - }, - <<"sysctls">> => #{ - <<"net.ipv4.ip_forward">> => <<"1">> - }, - <<"tmpfs">> => [ - <<"/tmp">> - ], - <<"extra_hosts">> => [ - <<"host1:192.168.0.1">> - ], - <<"healthcheck">> => #{ - <<"test">> => [ - <<"CMD-SHELL">>, - <<"curl -f http://localhost || exit 1">> - ], - <<"interval">> => <<"30s">>, - <<"timeout">> => <<"10s">>, - <<"retries">> => 3 - } - }, - create_container(<<"my_nginx_xx3">>, "/usr/local/code/efka/", M). +-export([create_container/3, check_container_exist/1, is_container_running/1, start_container/1, stop_container/1, remove_container/1, kill_container/1]). -spec pull_image(Image :: binary(), Callback :: fun((Msg :: any()) -> no_return())) -> ok | {error, ExitCode :: integer()}. pull_image(Image, Callback) when is_binary(Image), is_function(Callback, 1) -> @@ -210,6 +118,44 @@ stop_container(ContainerName) when is_binary(ContainerName) -> end end. +-spec kill_container(ContainerName :: binary()) -> ok | {error, Reason :: binary()}. +kill_container(ContainerName) when is_binary(ContainerName) -> + Url = lists:flatten(io_lib:format("/containers/~s/kill", [binary_to_list(ContainerName)])), + Headers = [ + {<<"Content-Type">>, <<"application/json">>} + ], + case docker_http:request("POST", Url, undefined, Headers) of + {ok, 204, _Headers, _} -> + ok; + {ok, _StatusCode, _Header, ErrorResp} -> + case catch jiffy:decode(ErrorResp) of + #{<<"message">> := Msg} -> + {error, Msg}; + _ -> + {error, ErrorResp} + end + end. + +-spec remove_container(ContainerName :: binary()) -> ok | {error, Reason :: binary()}. +remove_container(ContainerName) when is_binary(ContainerName) -> + Url = lists:flatten(io_lib:format("/containers/~s", [binary_to_list(ContainerName)])), + Headers = [ + {<<"Content-Type">>, <<"application/json">>} + ], + case docker_http:request("DELETE", Url, undefined, Headers) of + {ok, 204, _Headers, _} -> + ok; + {ok, 304, _Headers, _} -> + {error, <<"container already stopped">>}; + {ok, _StatusCode, _Header, ErrorResp} -> + case catch jiffy:decode(ErrorResp) of + #{<<"message">> := Msg} -> + {error, Msg}; + _ -> + {error, ErrorResp} + end + end. + -spec inspect_container(ContainerId :: binary()) -> {ok, Json :: map()} | {error, Error :: any()}. inspect_container(ContainerId) when is_binary(ContainerId) -> Url = lists:flatten(io_lib:format("/containers/~s/json", [binary_to_list(ContainerId)])), diff --git a/apps/efka/src/docker/docker_container_helper.erl b/apps/efka/src/docker/docker_container_helper.erl index aa7caa7..87910fc 100644 --- a/apps/efka/src/docker/docker_container_helper.erl +++ b/apps/efka/src/docker/docker_container_helper.erl @@ -19,10 +19,10 @@ ensure_dir(RootDir, ContainerName) when is_list(RootDir), is_binary(ContainerNam ok = filelib:ensure_dir(ContainerRootDir), {ok, ContainerRootDir}. --spec get_config_file(ContainerDir :: string()) -> {ok, EtcDir :: string()}. +-spec get_config_file(ContainerDir :: string()) -> ConfigFile :: string(). get_config_file(ContainerDir) when is_list(ContainerDir) -> %% 根目录 - {ok, ContainerDir ++ "/service.conf"}. + ContainerDir ++ "service.conf". -spec get_dir(RootDir :: string(), ContainerName :: binary()) -> {ok, ServerRootDir :: string()} | error. get_dir(RootDir, ContainerName) when is_list(RootDir), is_binary(ContainerName) -> diff --git a/apps/efka/src/docker/docker_manager.erl b/apps/efka/src/docker/docker_manager.erl index 92b618c..ee662d6 100644 --- a/apps/efka/src/docker/docker_manager.erl +++ b/apps/efka/src/docker/docker_manager.erl @@ -91,7 +91,7 @@ handle_call({config_container, ContainerName, Config}, _From, State = #state{roo case docker_container_helper:get_dir(RootDir, ContainerName) of {ok, ContainerDir} -> %% 覆盖容器的配置文件 - {ok, ConfigFile} = docker_container_helper:get_config_file(ContainerDir), + ConfigFile = docker_container_helper:get_config_file(ContainerDir), case file:write_file(ConfigFile, Config, [write, binary]) of ok -> lager:warning("[docker_manager] write config file: ~p success", [ConfigFile]),