fix build options
This commit is contained in:
parent
b6644de6e1
commit
2ec28bfc6e
@ -12,12 +12,92 @@
|
||||
%% 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]).
|
||||
-export([test/0, test_create_container/0]).
|
||||
|
||||
test() ->
|
||||
Image = <<"docker.1ms.run/library/nginx:latest">>,
|
||||
pull_image(Image, fun(Msg) -> lager:debug("msg is: ~p", [Msg]) end).
|
||||
|
||||
test_create_container() ->
|
||||
M = #{
|
||||
<<"image">> => <<"docker.1ms.run/library/nginx:latest">>,
|
||||
<<"container_name">> => <<"my_nginx_new">>,
|
||||
<<"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_xx">>, "/usr/local/code/efka/", M).
|
||||
|
||||
-spec pull_image(Image :: binary(), Callback :: fun((Msg :: binary()) -> no_return())) -> ok | {error, ExitCode :: integer()}.
|
||||
pull_image(Image, Callback) when is_binary(Image), is_function(Callback, 1) ->
|
||||
Url = io_lib:format("/images/create?fromImage=~s", [binary_to_list(Image)]),
|
||||
@ -36,35 +116,23 @@ check_image_exist(Image) when is_binary(Image) ->
|
||||
|
||||
-spec create_container(ContainerName :: binary(), ContainerDir :: string(), Config :: map()) -> {ok, ContainerId :: binary()} | {error, Reason :: any()}.
|
||||
create_container(ContainerName, ContainerDir, Config) when is_binary(ContainerName), is_list(ContainerDir), is_map(Config) ->
|
||||
Url = "/containers/create",
|
||||
Url = io_lib:format("/containers/create?name=~s", [binary_to_list(ContainerName)]),
|
||||
|
||||
Image = maps:get(<<"image">>, Config),
|
||||
Cmd = maps:get(<<"command">>, Config, []),
|
||||
|
||||
%% 挂载预留的目录,用来作为配置文件的存放
|
||||
BinContainerDir = list_to_binary(docker_container_helper:make_etc_dir_name(ContainerDir)),
|
||||
BaseOptions = [<<"-v">>, <<BinContainerDir/binary, ":/usr/local/etc/">>],
|
||||
|
||||
Options = build_options(Config),
|
||||
Args = lists:flatten([Image | BaseOptions ++ Options ++ Cmd]),
|
||||
CreateArgs = iolist_to_binary(lists:join(<<" ">>, Args)),
|
||||
|
||||
PortSettings = [stream, exit_status, stderr_to_stdout, use_stdio, binary],
|
||||
ExecCmd = "docker create --name " ++ binary_to_list(ContainerName) ++ " " ++ binary_to_list(CreateArgs),
|
||||
lager:debug("create_container cmd : ~p", [ExecCmd]),
|
||||
lists:foreach(fun({K, V}) ->
|
||||
lager:debug("~p => ~p", [K, V])
|
||||
end, maps:to_list(Options)),
|
||||
|
||||
case catch erlang:open_port({spawn, ExecCmd}, PortSettings) of
|
||||
Port when is_port(Port) ->
|
||||
case gather_output(Port) of
|
||||
{0, ContainerId} ->
|
||||
{ok, string:trim(ContainerId)};
|
||||
{ExitCode, Error} ->
|
||||
{error, {ExitCode, Error}}
|
||||
end;
|
||||
Error ->
|
||||
lager:debug("error: ~p", [Error]),
|
||||
{error, <<"exec command startup failed">>}
|
||||
end.
|
||||
|
||||
Body = iolist_to_binary(jiffy:encode(Options, [force_utf8])),
|
||||
Res = docker_http:request("POST", Url, Body, []),
|
||||
lager:debug("res is: ~p", [Res]).
|
||||
|
||||
-spec is_container_running(ContainerId :: binary()) -> boolean().
|
||||
is_container_running(ContainerId) when is_binary(ContainerId) ->
|
||||
@ -154,26 +222,28 @@ build_options(Config) when is_map(Config) ->
|
||||
<<"Image">> => maps:get(<<"image">>, Config, <<>>),
|
||||
<<"Cmd">> => maps:get(<<"command">>, Config, []),
|
||||
<<"Entrypoint">> => maps:get(<<"entrypoint">>, Config, []),
|
||||
<<"Env">> => maps:get(<<"envs">>, Config, [])
|
||||
<<"Env">> => maps:get(<<"envs">>, Config, []),
|
||||
<<"HostConfig">> => fold_merge([
|
||||
build_volumes(Config),
|
||||
build_restart(Config),
|
||||
build_privileged(Config),
|
||||
build_cap_add_drop(Config),
|
||||
build_devices(Config),
|
||||
build_memory(Config),
|
||||
build_cpu(Config),
|
||||
build_ulimits(Config),
|
||||
build_tmpfs(Config),
|
||||
build_extra_hosts(Config)
|
||||
])
|
||||
},
|
||||
fold_merge([
|
||||
build_expose(Config),
|
||||
build_volumes(Config),
|
||||
build_networks(Config),
|
||||
build_labels(Config),
|
||||
build_restart(Config),
|
||||
build_user(Config),
|
||||
build_working_dir(Config),
|
||||
build_hostname(Config),
|
||||
build_privileged(Config),
|
||||
build_cap_add_drop(Config),
|
||||
build_devices(Config),
|
||||
build_memory(Config),
|
||||
build_cpu(Config),
|
||||
build_ulimits(Config),
|
||||
build_sysctls(Config),
|
||||
build_tmpfs(Config),
|
||||
build_extra_hosts(Config),
|
||||
build_healthcheck(Config)
|
||||
])
|
||||
).
|
||||
@ -226,13 +296,6 @@ build_labels(Config) ->
|
||||
_ -> #{<<"Labels">> => Labels}
|
||||
end.
|
||||
|
||||
build_restart(Config) ->
|
||||
case maps:get(<<"restart">>, Config, undefined) of
|
||||
undefined ->
|
||||
#{};
|
||||
Policy ->
|
||||
#{<<"HostConfig">> => #{<<"RestartPolicy">> => #{<<"Name">> => Policy}}}
|
||||
end.
|
||||
|
||||
build_user(Config) ->
|
||||
case maps:get(<<"user">>, Config, undefined) of
|
||||
@ -258,58 +321,6 @@ build_hostname(Config) ->
|
||||
#{<<"Hostname">> => H}
|
||||
end.
|
||||
|
||||
build_privileged(Config) ->
|
||||
case maps:get(<<"privileged">>, Config, false) of
|
||||
true ->
|
||||
#{<<"HostConfig">> => #{<<"Privileged">> => true}};
|
||||
_ ->
|
||||
#{}
|
||||
end.
|
||||
|
||||
build_cap_add_drop(Config) ->
|
||||
Add = maps:get(<<"cap_add">>, Config, []),
|
||||
Drop = maps:get(<<"cap_drop">>, Config, []),
|
||||
case {Add, Drop} of
|
||||
{[], []} ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"HostConfig">> => #{<<"CapAdd">> => Add, <<"CapDrop">> => Drop}}
|
||||
end.
|
||||
|
||||
build_devices(Config) ->
|
||||
Devs = maps:get(<<"devices">>, Config, []),
|
||||
case Devs of
|
||||
[] ->
|
||||
#{};
|
||||
_ ->
|
||||
DevObjs = [#{<<"PathOnHost">> => H, <<"PathInContainer">> => C,
|
||||
<<"CgroupPermissions">> => <<"rwm">>}
|
||||
|| D <- Devs,
|
||||
[H, C] <- [binary:split(D, <<":">>, [])]],
|
||||
#{<<"HostConfig">> => #{<<"Devices">> => DevObjs}}
|
||||
end.
|
||||
|
||||
build_memory(Config) ->
|
||||
Mem = maps:get(<<"mem_limit">>, Config, undefined),
|
||||
MemRes = maps:get(<<"mem_reservation">>, Config, undefined),
|
||||
HCfg = #{},
|
||||
HCfg1 = if
|
||||
Mem /= undefined ->
|
||||
maps:put(<<"Memory">>, parse_mem(Mem), HCfg);
|
||||
true ->
|
||||
HCfg
|
||||
end,
|
||||
HCfg2 = if
|
||||
MemRes /= undefined ->
|
||||
maps:put(<<"MemoryReservation">>, parse_mem(MemRes), HCfg1);
|
||||
true ->
|
||||
HCfg1
|
||||
end,
|
||||
case maps:size(HCfg2) of
|
||||
0 -> #{};
|
||||
_ -> #{<<"HostConfig">> => HCfg2}
|
||||
end.
|
||||
|
||||
parse_mem(Val) ->
|
||||
case binary:last(Val) of
|
||||
$m ->
|
||||
@ -322,67 +333,7 @@ parse_mem(Val) ->
|
||||
list_to_integer(binary_to_list(Val))
|
||||
end.
|
||||
|
||||
build_cpu(Config) ->
|
||||
CPU = maps:get(<<"cpus">>, Config, undefined),
|
||||
Shares = maps:get(<<"cpu_shares">>, Config, undefined),
|
||||
HCfg = #{},
|
||||
HCfg1 = if
|
||||
CPU /= undefined ->
|
||||
maps:put(<<"NanoCpus">>, trunc(CPU * 1000000000), HCfg);
|
||||
true ->
|
||||
HCfg
|
||||
end,
|
||||
HCfg2 = if
|
||||
Shares /= undefined ->
|
||||
maps:put(<<"CpuShares">>, Shares, HCfg1);
|
||||
true ->
|
||||
HCfg1
|
||||
end,
|
||||
case maps:size(HCfg2) of
|
||||
0 -> #{};
|
||||
_ -> #{<<"HostConfig">> => HCfg2}
|
||||
end.
|
||||
|
||||
build_ulimits(Config) ->
|
||||
UL = maps:get(<<"ulimits">>, Config, #{}),
|
||||
case maps:size(UL) of
|
||||
0 -> #{};
|
||||
_ ->
|
||||
ULList = [#{<<"Name">> => K, <<"Soft">> => S, <<"Hard">> => H}
|
||||
|| {K, V} <- maps:to_list(UL),
|
||||
[S1, H1] <- [binary:split(V, <<":">>, [])],
|
||||
S = list_to_integer(binary_to_list(S1)),
|
||||
H = list_to_integer(binary_to_list(H1))],
|
||||
|
||||
#{<<"HostConfig">> => #{<<"Ulimits">> => ULList}}
|
||||
end.
|
||||
|
||||
build_sysctls(Config) ->
|
||||
SC = maps:get(<<"sysctls">>, Config, #{}),
|
||||
case maps:size(SC) of
|
||||
0 ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"HostConfig">> => #{<<"Sysctls">> => SC}}
|
||||
end.
|
||||
|
||||
build_tmpfs(Config) ->
|
||||
Tmp = maps:get(<<"tmpfs">>, Config, []),
|
||||
case Tmp of
|
||||
[] ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"HostConfig">> => #{<<"Tmpfs">> => maps:from_list([{T, <<>>} || T <- Tmp])}}
|
||||
end.
|
||||
|
||||
build_extra_hosts(Config) ->
|
||||
Hosts = maps:get(<<"extra_hosts">>, Config, []),
|
||||
case Hosts of
|
||||
[] ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"HostConfig">> => #{<<"ExtraHosts">> => Hosts}}
|
||||
end.
|
||||
|
||||
build_healthcheck(Config) ->
|
||||
HC = maps:get(<<"healthcheck">>, Config, #{}),
|
||||
@ -410,4 +361,140 @@ parse_duration(Bin) ->
|
||||
N * 60000000000;
|
||||
_ ->
|
||||
N
|
||||
end.
|
||||
|
||||
%% --- 构建子字段 ---
|
||||
build_volumes(Config) ->
|
||||
Vols = maps:get(<<"volumes">>, Config, []),
|
||||
case Vols of
|
||||
[] -> #{};
|
||||
_ ->
|
||||
HostBinds = Vols,
|
||||
VolMap = maps:from_list(lists:map(fun(V) ->
|
||||
[_Host, Cont] = binary:split(V, <<":">>, []),
|
||||
{Cont, #{}}
|
||||
end, Vols)),
|
||||
#{
|
||||
<<"HostConfig">> => #{
|
||||
<<"Binds">> => HostBinds
|
||||
},
|
||||
<<"Volumes">> => VolMap
|
||||
}
|
||||
end.
|
||||
|
||||
build_restart(Config) ->
|
||||
case maps:get(<<"restart">>, Config, undefined) of
|
||||
undefined ->
|
||||
#{};
|
||||
Policy ->
|
||||
#{<<"RestartPolicy">> => #{<<"Name">> => Policy}}
|
||||
end.
|
||||
|
||||
build_privileged(Config) ->
|
||||
case maps:get(<<"privileged">>, Config, false) of
|
||||
true ->
|
||||
#{<<"Privileged">> => true};
|
||||
_ ->
|
||||
#{}
|
||||
end.
|
||||
|
||||
build_cap_add_drop(Config) ->
|
||||
Add = maps:get(<<"cap_add">>, Config, []),
|
||||
Drop = maps:get(<<"cap_drop">>, Config, []),
|
||||
case {Add, Drop} of
|
||||
{[], []} ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"CapAdd">> => Add, <<"CapDrop">> => Drop}
|
||||
end.
|
||||
|
||||
build_devices(Config) ->
|
||||
Devs = maps:get(<<"devices">>, Config, []),
|
||||
case Devs of
|
||||
[] ->
|
||||
#{};
|
||||
_ ->
|
||||
DevObjs = [#{<<"PathOnHost">> => H, <<"PathInContainer">> => C,
|
||||
<<"CgroupPermissions">> => <<"rwm">>}
|
||||
|| D <- Devs,
|
||||
[H, C] <- [binary:split(D, <<":">>, [])]],
|
||||
#{<<"Devices">> => DevObjs}
|
||||
end.
|
||||
|
||||
build_memory(Config) ->
|
||||
Mem = maps:get(<<"mem_limit">>, Config, undefined),
|
||||
MemRes = maps:get(<<"mem_reservation">>, Config, undefined),
|
||||
HCfg = #{},
|
||||
HCfg1 = if
|
||||
Mem /= undefined ->
|
||||
maps:put(<<"Memory">>, parse_mem(Mem), HCfg);
|
||||
true ->
|
||||
HCfg
|
||||
end,
|
||||
if
|
||||
MemRes /= undefined ->
|
||||
maps:put(<<"MemoryReservation">>, parse_mem(MemRes), HCfg1);
|
||||
true ->
|
||||
HCfg1
|
||||
end.
|
||||
|
||||
|
||||
build_cpu(Config) ->
|
||||
CPU = maps:get(<<"cpus">>, Config, undefined),
|
||||
Shares = maps:get(<<"cpu_shares">>, Config, undefined),
|
||||
HCfg = #{},
|
||||
HCfg1 = if
|
||||
CPU /= undefined ->
|
||||
maps:put(<<"NanoCpus">>, trunc(CPU * 1000000000), HCfg);
|
||||
true ->
|
||||
HCfg
|
||||
end,
|
||||
if
|
||||
Shares /= undefined ->
|
||||
maps:put(<<"CpuShares">>, Shares, HCfg1);
|
||||
true ->
|
||||
HCfg1
|
||||
end.
|
||||
|
||||
build_ulimits(Config) ->
|
||||
UL = maps:get(<<"ulimits">>, Config, #{}),
|
||||
case maps:size(UL) of
|
||||
0 ->
|
||||
#{};
|
||||
_ ->
|
||||
ULList = lists:map(fun({K, V}) ->
|
||||
[S1, H1] = binary:split(V, <<":">>, []),
|
||||
S = list_to_integer(binary_to_list(S1)),
|
||||
H = list_to_integer(binary_to_list(H1)),
|
||||
#{<<"Name">> => K, <<"Soft">> => S, <<"Hard">> => H}
|
||||
end, maps:to_list(UL)),
|
||||
|
||||
#{<<"Ulimits">> => ULList}
|
||||
end.
|
||||
|
||||
build_sysctls(Config) ->
|
||||
SC = maps:get(<<"sysctls">>, Config, #{}),
|
||||
case maps:size(SC) of
|
||||
0 ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"Sysctls">> => SC}
|
||||
end.
|
||||
|
||||
build_tmpfs(Config) ->
|
||||
Tmp = maps:get(<<"tmpfs">>, Config, []),
|
||||
case Tmp of
|
||||
[] ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"Tmpfs">> => maps:from_list([{T, <<>>} || T <- Tmp])}
|
||||
end.
|
||||
|
||||
build_extra_hosts(Config) ->
|
||||
Hosts = maps:get(<<"extra_hosts">>, Config, []),
|
||||
case Hosts of
|
||||
[] ->
|
||||
#{};
|
||||
_ ->
|
||||
#{<<"ExtraHosts">> => Hosts}
|
||||
end.
|
||||
Loading…
x
Reference in New Issue
Block a user