简化docker容器的创建逻辑
This commit is contained in:
parent
dae690b20e
commit
8a108ec34d
@ -121,51 +121,74 @@
|
|||||||
-record('ContainerDeployParams',
|
-record('ContainerDeployParams',
|
||||||
{container_name = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
{container_name = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
container_dir = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
container_dir = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||||
spec = undefined :: message_pb:'ContainerSpec'() | undefined % = 3, optional
|
create = undefined :: message_pb:'DockerCreateOptions'() | undefined % = 3, optional
|
||||||
}).
|
}).
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-ifndef('CONTAINERSPEC_PB_H').
|
-ifndef('DOCKERCREATEOPTIONS_PB_H').
|
||||||
-define('CONTAINERSPEC_PB_H', true).
|
-define('DOCKERCREATEOPTIONS_PB_H', true).
|
||||||
-record('ContainerSpec',
|
-record('DockerCreateOptions',
|
||||||
|
{config = undefined :: message_pb:'DockerContainerConfig'() | undefined, % = 1, optional
|
||||||
|
host_config = undefined :: message_pb:'DockerHostConfig'() | undefined, % = 2, optional
|
||||||
|
networking_config = undefined :: message_pb:'DockerNetworkingConfig'() | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('DOCKERCONTAINERCONFIG_PB_H').
|
||||||
|
-define('DOCKERCONTAINERCONFIG_PB_H', true).
|
||||||
|
-record('DockerContainerConfig',
|
||||||
{image = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
{image = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
command = [] :: [unicode:chardata()] | undefined, % = 2, repeated
|
cmd = [] :: [unicode:chardata()] | undefined, % = 2, repeated
|
||||||
entrypoint = [] :: [unicode:chardata()] | undefined, % = 3, repeated
|
entrypoint = [] :: [unicode:chardata()] | undefined, % = 3, repeated
|
||||||
env = [] :: [unicode:chardata()] | undefined, % = 4, repeated
|
env = [] :: [unicode:chardata()] | undefined, % = 4, repeated
|
||||||
labels = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 5
|
labels = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 5
|
||||||
volumes = [] :: [message_pb:'VolumeBind'()] | undefined, % = 6, repeated
|
volumes = [] :: [unicode:chardata()] | undefined, % = 6, repeated
|
||||||
user = <<>> :: unicode:chardata() | undefined, % = 7, optional
|
user = <<>> :: unicode:chardata() | undefined, % = 7, optional
|
||||||
working_dir = <<>> :: unicode:chardata() | undefined, % = 8, optional
|
working_dir = <<>> :: unicode:chardata() | undefined, % = 8, optional
|
||||||
hostname = <<>> :: unicode:chardata() | undefined, % = 9, optional
|
hostname = <<>> :: unicode:chardata() | undefined, % = 9, optional
|
||||||
expose = [] :: [message_pb:'PortExpose'()] | undefined, % = 10, repeated
|
exposed_ports = [] :: [message_pb:'DockerExposedPort'()] | undefined, % = 10, repeated
|
||||||
networks = [] :: [unicode:chardata()] | undefined, % = 11, repeated
|
healthcheck = undefined :: message_pb:'Healthcheck'() | undefined % = 11, optional
|
||||||
network_mode = <<>> :: unicode:chardata() | undefined, % = 12, optional
|
|
||||||
healthcheck = undefined :: message_pb:'Healthcheck'() | undefined, % = 13, optional
|
|
||||||
restart = undefined :: message_pb:'RestartPolicy'() | undefined, % = 14, optional
|
|
||||||
privileged = false :: boolean() | 0 | 1 | undefined, % = 15, optional
|
|
||||||
cap_add = [] :: [unicode:chardata()] | undefined, % = 16, repeated
|
|
||||||
cap_drop = [] :: [unicode:chardata()] | undefined, % = 17, repeated
|
|
||||||
devices = [] :: [message_pb:'DeviceMapping'()] | undefined, % = 18, repeated
|
|
||||||
resources = undefined :: message_pb:'ResourceLimits'() | undefined, % = 19, optional
|
|
||||||
ulimits = [] :: [message_pb:'Ulimit'()] | undefined, % = 20, repeated
|
|
||||||
tmpfs = [] :: [message_pb:'TmpfsMount'()] | undefined, % = 21, repeated
|
|
||||||
sysctls = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 22
|
|
||||||
extra_hosts = [] :: [unicode:chardata()] | undefined % = 23, repeated
|
|
||||||
}).
|
}).
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-ifndef('VOLUMEBIND_PB_H').
|
-ifndef('DOCKERHOSTCONFIG_PB_H').
|
||||||
-define('VOLUMEBIND_PB_H', true).
|
-define('DOCKERHOSTCONFIG_PB_H', true).
|
||||||
-record('VolumeBind',
|
-record('DockerHostConfig',
|
||||||
{host_path = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
{binds = [] :: [unicode:chardata()] | undefined, % = 1, repeated
|
||||||
container_path = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
network_mode = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||||
read_only = false :: boolean() | 0 | 1 | undefined % = 3, optional
|
restart_policy = undefined :: message_pb:'RestartPolicy'() | undefined, % = 3, optional
|
||||||
|
privileged = false :: boolean() | 0 | 1 | undefined, % = 4, optional
|
||||||
|
cap_add = [] :: [unicode:chardata()] | undefined, % = 5, repeated
|
||||||
|
cap_drop = [] :: [unicode:chardata()] | undefined, % = 6, repeated
|
||||||
|
devices = [] :: [message_pb:'DeviceMapping'()] | undefined, % = 7, repeated
|
||||||
|
memory = 0 :: non_neg_integer() | undefined, % = 8, optional, 64 bits
|
||||||
|
memory_reservation = 0 :: non_neg_integer() | undefined, % = 9, optional, 64 bits
|
||||||
|
nano_cpus = 0 :: non_neg_integer() | undefined, % = 10, optional, 64 bits
|
||||||
|
cpu_shares = 0 :: non_neg_integer() | undefined, % = 11, optional, 64 bits
|
||||||
|
ulimits = [] :: [message_pb:'Ulimit'()] | undefined, % = 12, repeated
|
||||||
|
tmpfs = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 13
|
||||||
|
sysctls = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 14
|
||||||
|
extra_hosts = [] :: [unicode:chardata()] | undefined % = 15, repeated
|
||||||
}).
|
}).
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-ifndef('PORTEXPOSE_PB_H').
|
-ifndef('DOCKERNETWORKINGCONFIG_PB_H').
|
||||||
-define('PORTEXPOSE_PB_H', true).
|
-define('DOCKERNETWORKINGCONFIG_PB_H', true).
|
||||||
-record('PortExpose',
|
-record('DockerNetworkingConfig',
|
||||||
|
{endpoints = [] :: [message_pb:'DockerNetworkEndpoint'()] | undefined % = 1, repeated
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('DOCKERNETWORKENDPOINT_PB_H').
|
||||||
|
-define('DOCKERNETWORKENDPOINT_PB_H', true).
|
||||||
|
-record('DockerNetworkEndpoint',
|
||||||
|
{name = <<>> :: unicode:chardata() | undefined % = 1, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('DOCKEREXPOSEDPORT_PB_H').
|
||||||
|
-define('DOCKEREXPOSEDPORT_PB_H', true).
|
||||||
|
-record('DockerExposedPort',
|
||||||
{container_port = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
{container_port = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||||
protocol = <<>> :: unicode:chardata() | undefined % = 2, optional
|
protocol = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||||
}).
|
}).
|
||||||
@ -198,16 +221,6 @@
|
|||||||
}).
|
}).
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-ifndef('RESOURCELIMITS_PB_H').
|
|
||||||
-define('RESOURCELIMITS_PB_H', true).
|
|
||||||
-record('ResourceLimits',
|
|
||||||
{memory_bytes = 0 :: non_neg_integer() | undefined, % = 1, optional, 64 bits
|
|
||||||
memory_reservation_bytes = 0 :: non_neg_integer() | undefined, % = 2, optional, 64 bits
|
|
||||||
nano_cpus = 0 :: non_neg_integer() | undefined, % = 3, optional, 64 bits
|
|
||||||
cpu_shares = 0 :: non_neg_integer() | undefined % = 4, optional, 64 bits
|
|
||||||
}).
|
|
||||||
-endif.
|
|
||||||
|
|
||||||
-ifndef('ULIMIT_PB_H').
|
-ifndef('ULIMIT_PB_H').
|
||||||
-define('ULIMIT_PB_H', true).
|
-define('ULIMIT_PB_H', true).
|
||||||
-record('Ulimit',
|
-record('Ulimit',
|
||||||
@ -217,14 +230,6 @@
|
|||||||
}).
|
}).
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-ifndef('TMPFSMOUNT_PB_H').
|
|
||||||
-define('TMPFSMOUNT_PB_H', true).
|
|
||||||
-record('TmpfsMount',
|
|
||||||
{path = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
|
||||||
options = <<>> :: unicode:chardata() | undefined % = 2, optional
|
|
||||||
}).
|
|
||||||
-endif.
|
|
||||||
|
|
||||||
-ifndef('AUTHREQUEST_PB_H').
|
-ifndef('AUTHREQUEST_PB_H').
|
||||||
-define('AUTHREQUEST_PB_H', true).
|
-define('AUTHREQUEST_PB_H', true).
|
||||||
-record('AuthRequest',
|
-record('AuthRequest',
|
||||||
|
|||||||
@ -91,48 +91,57 @@ message ContainerRequest {
|
|||||||
message ContainerDeployParams {
|
message ContainerDeployParams {
|
||||||
string container_name = 1;
|
string container_name = 1;
|
||||||
string container_dir = 2;
|
string container_dir = 2;
|
||||||
ContainerSpec spec = 3;
|
DockerCreateOptions create = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContainerSpec {
|
message DockerCreateOptions {
|
||||||
|
DockerContainerConfig config = 1;
|
||||||
|
DockerHostConfig host_config = 2;
|
||||||
|
DockerNetworkingConfig networking_config = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DockerContainerConfig {
|
||||||
string image = 1;
|
string image = 1;
|
||||||
repeated string command = 2;
|
repeated string cmd = 2;
|
||||||
repeated string entrypoint = 3;
|
repeated string entrypoint = 3;
|
||||||
|
|
||||||
repeated string env = 4;
|
repeated string env = 4;
|
||||||
map<string, string> labels = 5;
|
map<string, string> labels = 5;
|
||||||
|
repeated string volumes = 6;
|
||||||
repeated VolumeBind volumes = 6;
|
|
||||||
string user = 7;
|
string user = 7;
|
||||||
string working_dir = 8;
|
string working_dir = 8;
|
||||||
string hostname = 9;
|
string hostname = 9;
|
||||||
|
repeated DockerExposedPort exposed_ports = 10;
|
||||||
repeated PortExpose expose = 10;
|
Healthcheck healthcheck = 11;
|
||||||
repeated string networks = 11;
|
|
||||||
string network_mode = 12;
|
|
||||||
|
|
||||||
Healthcheck healthcheck = 13;
|
|
||||||
RestartPolicy restart = 14;
|
|
||||||
|
|
||||||
bool privileged = 15;
|
|
||||||
repeated string cap_add = 16;
|
|
||||||
repeated string cap_drop = 17;
|
|
||||||
repeated DeviceMapping devices = 18;
|
|
||||||
|
|
||||||
ResourceLimits resources = 19;
|
|
||||||
repeated Ulimit ulimits = 20;
|
|
||||||
repeated TmpfsMount tmpfs = 21;
|
|
||||||
map<string, string> sysctls = 22;
|
|
||||||
repeated string extra_hosts = 23;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message VolumeBind {
|
message DockerHostConfig {
|
||||||
string host_path = 1;
|
repeated string binds = 1;
|
||||||
string container_path = 2;
|
string network_mode = 2;
|
||||||
bool read_only = 3;
|
RestartPolicy restart_policy = 3;
|
||||||
|
bool privileged = 4;
|
||||||
|
repeated string cap_add = 5;
|
||||||
|
repeated string cap_drop = 6;
|
||||||
|
repeated DeviceMapping devices = 7;
|
||||||
|
uint64 memory = 8;
|
||||||
|
uint64 memory_reservation = 9;
|
||||||
|
uint64 nano_cpus = 10;
|
||||||
|
uint64 cpu_shares = 11;
|
||||||
|
repeated Ulimit ulimits = 12;
|
||||||
|
map<string, string> tmpfs = 13;
|
||||||
|
map<string, string> sysctls = 14;
|
||||||
|
repeated string extra_hosts = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PortExpose {
|
message DockerNetworkingConfig {
|
||||||
|
repeated DockerNetworkEndpoint endpoints = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DockerNetworkEndpoint {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DockerExposedPort {
|
||||||
uint32 container_port = 1;
|
uint32 container_port = 1;
|
||||||
string protocol = 2; // tcp / udp
|
string protocol = 2; // tcp / udp
|
||||||
}
|
}
|
||||||
@ -155,24 +164,12 @@ message DeviceMapping {
|
|||||||
string cgroup_permissions = 3; // 默认可填 rwm
|
string cgroup_permissions = 3; // 默认可填 rwm
|
||||||
}
|
}
|
||||||
|
|
||||||
message ResourceLimits {
|
|
||||||
uint64 memory_bytes = 1;
|
|
||||||
uint64 memory_reservation_bytes = 2;
|
|
||||||
uint64 nano_cpus = 3;
|
|
||||||
uint64 cpu_shares = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Ulimit {
|
message Ulimit {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
uint64 soft = 2;
|
uint64 soft = 2;
|
||||||
uint64 hard = 3;
|
uint64 hard = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TmpfsMount {
|
|
||||||
string path = 1;
|
|
||||||
string options = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AuthRequest {
|
message AuthRequest {
|
||||||
bytes uuid = 1;
|
bytes uuid = 1;
|
||||||
bytes username = 2;
|
bytes username = 2;
|
||||||
|
|||||||
@ -36,19 +36,14 @@ check_image_exist(Image) when is_binary(Image) ->
|
|||||||
{ok, ContainerId :: binary()} | {error, Reason :: any()}.
|
{ok, ContainerId :: binary()} | {error, Reason :: any()}.
|
||||||
create_container(ContainerDir, #'ContainerDeployParams'{
|
create_container(ContainerDir, #'ContainerDeployParams'{
|
||||||
container_name = ContainerName,
|
container_name = ContainerName,
|
||||||
spec = Spec0 = #'ContainerSpec'{volumes = Volumes0}
|
create = Create0
|
||||||
}) when is_binary(ContainerName), is_list(ContainerDir) ->
|
}) when is_binary(ContainerName), is_list(ContainerDir) ->
|
||||||
|
|
||||||
Url = lists:flatten(io_lib:format("/containers/create?name=~s", [binary_to_list(ContainerName)])),
|
Url = lists:flatten(io_lib:format("/containers/create?name=~s", [binary_to_list(ContainerName)])),
|
||||||
%% 挂载预留的目录,用来作为配置文件的存放
|
%% 挂载预留的目录,用来作为配置文件的存放
|
||||||
ConfigFile = list_to_binary(docker_helper:get_config_file(ContainerDir)),
|
ConfigFile = list_to_binary(docker_helper:get_config_file(ContainerDir)),
|
||||||
ConfigVolume = #'VolumeBind'{
|
Create = patch_create_options(ContainerName, ConfigFile, Create0),
|
||||||
host_path = ConfigFile,
|
Options = build_options(Create),
|
||||||
container_path = <<"/usr/local/etc/service.conf">>,
|
|
||||||
read_only = false
|
|
||||||
},
|
|
||||||
Spec = Spec0#'ContainerSpec'{volumes = [ConfigVolume | Volumes0]},
|
|
||||||
Options = build_options(ContainerName, Spec),
|
|
||||||
display_options(Options),
|
display_options(Options),
|
||||||
|
|
||||||
Body = iolist_to_binary(jiffy:encode(Options, [force_utf8])),
|
Body = iolist_to_binary(jiffy:encode(Options, [force_utf8])),
|
||||||
@ -239,45 +234,100 @@ inspect_container(ContainerId) when is_binary(ContainerId) ->
|
|||||||
%%% helper methods
|
%%% helper methods
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
patch_create_options(ContainerName, ConfigFile, undefined) ->
|
||||||
|
patch_create_options(ContainerName, ConfigFile, #'DockerCreateOptions'{});
|
||||||
|
patch_create_options(ContainerName, ConfigFile, Create = #'DockerCreateOptions'{
|
||||||
|
config = Config0,
|
||||||
|
host_config = HostConfig0
|
||||||
|
}) when is_binary(ContainerName), is_binary(ConfigFile) ->
|
||||||
|
Config = patch_container_config(ContainerName, ensure_container_config(Config0)),
|
||||||
|
HostConfig = patch_host_config(ConfigFile, ensure_host_config(HostConfig0)),
|
||||||
|
Create#'DockerCreateOptions'{config = Config, host_config = HostConfig}.
|
||||||
|
|
||||||
|
patch_container_config(ContainerName, Config = #'DockerContainerConfig'{env = Env0, volumes = Volumes0})
|
||||||
|
when is_binary(ContainerName) ->
|
||||||
|
ConfigVolume = <<"/usr/local/etc/service.conf">>,
|
||||||
|
Envs0 = [<<"CONTAINER_NAME=", ContainerName/binary>>],
|
||||||
|
Envs = add_unique_front(Envs0, [to_binary(EnvItem) || EnvItem <- Env0]),
|
||||||
|
Volumes = add_unique_front([ConfigVolume], [to_binary(Volume) || Volume <- Volumes0]),
|
||||||
|
Config#'DockerContainerConfig'{env = Envs, volumes = Volumes}.
|
||||||
|
|
||||||
|
patch_host_config(ConfigFile, HostConfig = #'DockerHostConfig'{binds = Binds0}) when is_binary(ConfigFile) ->
|
||||||
|
ConfigBind = <<ConfigFile/binary, ":/usr/local/etc/service.conf">>,
|
||||||
|
Binds = add_unique_front([ConfigBind], [to_binary(Bind) || Bind <- Binds0]),
|
||||||
|
HostConfig#'DockerHostConfig'{binds = Binds}.
|
||||||
|
|
||||||
|
ensure_container_config(undefined) ->
|
||||||
|
#'DockerContainerConfig'{};
|
||||||
|
ensure_container_config(Config = #'DockerContainerConfig'{}) ->
|
||||||
|
Config.
|
||||||
|
|
||||||
|
ensure_host_config(undefined) ->
|
||||||
|
#'DockerHostConfig'{};
|
||||||
|
ensure_host_config(HostConfig = #'DockerHostConfig'{}) ->
|
||||||
|
HostConfig.
|
||||||
|
|
||||||
%% 构建最终 JSON Map
|
%% 构建最终 JSON Map
|
||||||
build_options(ContainerName, Spec = #'ContainerSpec'{
|
build_options(#'DockerCreateOptions'{
|
||||||
image = Image,
|
config = #'DockerContainerConfig'{
|
||||||
command = Command,
|
image = Image,
|
||||||
entrypoint = Entrypoint,
|
cmd = Cmd,
|
||||||
env = Env,
|
entrypoint = Entrypoint,
|
||||||
labels = Labels,
|
env = Env,
|
||||||
user = User,
|
labels = Labels,
|
||||||
working_dir = WorkingDir,
|
volumes = Volumes,
|
||||||
hostname = Hostname
|
user = User,
|
||||||
}) when is_binary(ContainerName) ->
|
working_dir = WorkingDir,
|
||||||
%% 容器名称作为环境变量,注入到运行时环境中
|
hostname = Hostname,
|
||||||
Envs0 = [to_binary(EnvItem) || EnvItem <- Env],
|
exposed_ports = ExposedPorts,
|
||||||
Envs = [<<"CONTAINER_NAME=", ContainerName/binary>>|Envs0],
|
healthcheck = Healthcheck
|
||||||
|
},
|
||||||
|
host_config = #'DockerHostConfig'{
|
||||||
|
binds = Binds,
|
||||||
|
network_mode = NetworkMode,
|
||||||
|
restart_policy = RestartPolicy,
|
||||||
|
privileged = Privileged,
|
||||||
|
cap_add = CapAdd,
|
||||||
|
cap_drop = CapDrop,
|
||||||
|
devices = Devices,
|
||||||
|
memory = Memory,
|
||||||
|
memory_reservation = MemoryReservation,
|
||||||
|
nano_cpus = NanoCpus,
|
||||||
|
cpu_shares = CpuShares,
|
||||||
|
ulimits = Ulimits,
|
||||||
|
tmpfs = Tmpfs,
|
||||||
|
sysctls = Sysctls,
|
||||||
|
extra_hosts = ExtraHosts
|
||||||
|
},
|
||||||
|
networking_config = #'DockerNetworkingConfig'{
|
||||||
|
endpoints = Endpoints
|
||||||
|
}
|
||||||
|
}) ->
|
||||||
#{
|
#{
|
||||||
<<"Image">> => to_binary(Image),
|
<<"Image">> => to_binary(Image),
|
||||||
<<"Cmd">> => [to_binary(CommandItem) || CommandItem <- Command],
|
<<"Cmd">> => [to_binary(CommandItem) || CommandItem <- Cmd],
|
||||||
<<"Entrypoint">> => [to_binary(EntrypointItem) || EntrypointItem <- Entrypoint],
|
<<"Entrypoint">> => [to_binary(EntrypointItem) || EntrypointItem <- Entrypoint],
|
||||||
<<"Env">> => Envs,
|
<<"Env">> => [to_binary(EnvItem) || EnvItem <- Env],
|
||||||
<<"Labels">> => maps:from_list([{to_binary(Key), to_binary(Value)} || {Key, Value} <- Labels]),
|
<<"Labels">> => maps:from_list([{to_binary(Key), to_binary(Value)} || {Key, Value} <- Labels]),
|
||||||
<<"Volumes">> => build_volumes(Spec),
|
<<"Volumes">> => build_volumes(Volumes),
|
||||||
<<"User">> => to_binary(User),
|
<<"User">> => to_binary(User),
|
||||||
<<"WorkingDir">> => to_binary(WorkingDir),
|
<<"WorkingDir">> => to_binary(WorkingDir),
|
||||||
<<"Hostname">> => to_binary(Hostname),
|
<<"Hostname">> => to_binary(Hostname),
|
||||||
<<"ExposedPorts">> => build_expose(Spec),
|
<<"ExposedPorts">> => build_expose(ExposedPorts),
|
||||||
<<"NetworkingConfig">> => build_networks(Spec),
|
<<"NetworkingConfig">> => build_networking_config(Endpoints),
|
||||||
<<"Healthcheck">> => build_healthcheck(Spec),
|
<<"Healthcheck">> => build_healthcheck(Healthcheck),
|
||||||
<<"HostConfig">> => fold_merge([
|
<<"HostConfig">> => fold_merge([
|
||||||
build_network_mode(Spec),
|
build_binds(Binds),
|
||||||
build_binds(Spec),
|
build_network_mode(NetworkMode),
|
||||||
build_restart(Spec),
|
build_restart(RestartPolicy),
|
||||||
build_privileged(Spec),
|
build_privileged(Privileged),
|
||||||
build_cap_add_drop(Spec),
|
build_cap_add_drop(CapAdd, CapDrop),
|
||||||
build_devices(Spec),
|
build_devices(Devices),
|
||||||
build_resources(Spec),
|
build_resources(Memory, MemoryReservation, NanoCpus, CpuShares),
|
||||||
build_ulimits(Spec),
|
build_ulimits(Ulimits),
|
||||||
build_tmpfs(Spec),
|
build_tmpfs(Tmpfs),
|
||||||
build_sysctls(Spec),
|
build_sysctls(Sysctls),
|
||||||
build_extra_hosts(Spec)
|
build_extra_hosts(ExtraHosts)
|
||||||
])
|
])
|
||||||
}.
|
}.
|
||||||
|
|
||||||
@ -286,50 +336,50 @@ fold_merge(List) ->
|
|||||||
lists:foldl(fun maps:merge/2, #{}, List).
|
lists:foldl(fun maps:merge/2, #{}, List).
|
||||||
|
|
||||||
%% --- 构建子字段 ---
|
%% --- 构建子字段 ---
|
||||||
build_expose(#'ContainerSpec'{expose = Ports}) ->
|
build_expose(Ports) when is_list(Ports) ->
|
||||||
case Ports of
|
case Ports of
|
||||||
[] -> #{};
|
[] -> #{};
|
||||||
_ ->
|
_ ->
|
||||||
maps:from_list([{normalize_expose_port(P), #{}} || P <- Ports])
|
maps:from_list([{normalize_expose_port(P), #{}} || P <- Ports])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_volumes(#'ContainerSpec'{volumes = Vols}) ->
|
build_volumes(Vols) when is_list(Vols) ->
|
||||||
case Vols of
|
case Vols of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
_ ->
|
_ ->
|
||||||
maps:from_list([{to_binary(Cont), #{}} || #'VolumeBind'{container_path = Cont} <- Vols])
|
maps:from_list([{to_binary(Cont), #{}} || Cont <- Vols])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_binds(#'ContainerSpec'{volumes = Vols}) ->
|
build_binds(Binds) when is_list(Binds) ->
|
||||||
case Vols of
|
case Binds of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
_ ->
|
_ ->
|
||||||
#{<<"Binds">> => [volume_bind(Vol) || Vol <- Vols]}
|
#{<<"Binds">> => [to_binary(Bind) || Bind <- Binds]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_networks(#'ContainerSpec'{networks = Nets}) ->
|
build_networking_config(Endpoints) when is_list(Endpoints) ->
|
||||||
case Nets of
|
case Endpoints of
|
||||||
[] -> #{};
|
[] -> #{};
|
||||||
_ ->
|
_ ->
|
||||||
NetCfg = maps:from_list([{to_binary(N), #{}} || N <- Nets]),
|
NetCfg = maps:from_list([{to_binary(Name), #{}} || #'DockerNetworkEndpoint'{name = Name} <- Endpoints]),
|
||||||
#{<<"EndpointsConfig">> => NetCfg}
|
#{<<"EndpointsConfig">> => NetCfg}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_network_mode(#'ContainerSpec'{network_mode = <<>>}) ->
|
build_network_mode(<<>>) ->
|
||||||
#{};
|
#{};
|
||||||
build_network_mode(#'ContainerSpec'{network_mode = NetworkMode}) ->
|
build_network_mode(NetworkMode) ->
|
||||||
#{<<"NetworkMode">> => to_binary(NetworkMode)}.
|
#{<<"NetworkMode">> => to_binary(NetworkMode)}.
|
||||||
|
|
||||||
build_healthcheck(#'ContainerSpec'{healthcheck = undefined}) ->
|
build_healthcheck(undefined) ->
|
||||||
#{};
|
#{};
|
||||||
build_healthcheck(#'ContainerSpec'{healthcheck = #'Healthcheck'{
|
build_healthcheck(#'Healthcheck'{
|
||||||
test = Test,
|
test = Test,
|
||||||
interval_ns = IntervalNs,
|
interval_ns = IntervalNs,
|
||||||
timeout_ns = TimeoutNs,
|
timeout_ns = TimeoutNs,
|
||||||
retries = Retries
|
retries = Retries
|
||||||
}}) ->
|
}) ->
|
||||||
#{
|
#{
|
||||||
<<"Test">> => [to_binary(Item) || Item <- Test],
|
<<"Test">> => [to_binary(Item) || Item <- Test],
|
||||||
<<"Interval">> => IntervalNs,
|
<<"Interval">> => IntervalNs,
|
||||||
@ -337,12 +387,12 @@ build_healthcheck(#'ContainerSpec'{healthcheck = #'Healthcheck'{
|
|||||||
<<"Retries">> => Retries
|
<<"Retries">> => Retries
|
||||||
}.
|
}.
|
||||||
|
|
||||||
build_restart(#'ContainerSpec'{restart = undefined}) ->
|
build_restart(undefined) ->
|
||||||
#{};
|
#{};
|
||||||
build_restart(#'ContainerSpec'{restart = #'RestartPolicy'{
|
build_restart(#'RestartPolicy'{
|
||||||
name = Name,
|
name = Name,
|
||||||
maximum_retry_count = RetryCount
|
maximum_retry_count = RetryCount
|
||||||
}}) ->
|
}) ->
|
||||||
RestartPolicy = #{
|
RestartPolicy = #{
|
||||||
<<"Name">> => to_binary(Name)
|
<<"Name">> => to_binary(Name)
|
||||||
},
|
},
|
||||||
@ -355,7 +405,7 @@ build_restart(#'ContainerSpec'{restart = #'RestartPolicy'{
|
|||||||
}}
|
}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_privileged(#'ContainerSpec'{privileged = Privileged}) ->
|
build_privileged(Privileged) ->
|
||||||
case to_bool(Privileged) of
|
case to_bool(Privileged) of
|
||||||
true ->
|
true ->
|
||||||
#{<<"Privileged">> => true};
|
#{<<"Privileged">> => true};
|
||||||
@ -363,7 +413,7 @@ build_privileged(#'ContainerSpec'{privileged = Privileged}) ->
|
|||||||
#{}
|
#{}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_cap_add_drop(#'ContainerSpec'{cap_add = Add, cap_drop = Drop}) ->
|
build_cap_add_drop(Add, Drop) when is_list(Add), is_list(Drop) ->
|
||||||
case {Add, Drop} of
|
case {Add, Drop} of
|
||||||
{[], []} ->
|
{[], []} ->
|
||||||
#{};
|
#{};
|
||||||
@ -374,7 +424,7 @@ build_cap_add_drop(#'ContainerSpec'{cap_add = Add, cap_drop = Drop}) ->
|
|||||||
}
|
}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_devices(#'ContainerSpec'{devices = Devs}) ->
|
build_devices(Devs) when is_list(Devs) ->
|
||||||
case Devs of
|
case Devs of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
@ -391,14 +441,7 @@ build_devices(#'ContainerSpec'{devices = Devs}) ->
|
|||||||
#{<<"Devices">> => DevObjs}
|
#{<<"Devices">> => DevObjs}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_resources(#'ContainerSpec'{resources = undefined}) ->
|
build_resources(MemoryBytes, ReservationBytes, NanoCpus, CpuShares) ->
|
||||||
#{};
|
|
||||||
build_resources(#'ContainerSpec'{resources = #'ResourceLimits'{
|
|
||||||
memory_bytes = MemoryBytes,
|
|
||||||
memory_reservation_bytes = ReservationBytes,
|
|
||||||
nano_cpus = NanoCpus,
|
|
||||||
cpu_shares = CpuShares
|
|
||||||
}}) ->
|
|
||||||
HostConfig0 = #{},
|
HostConfig0 = #{},
|
||||||
HostConfig1 = case MemoryBytes of
|
HostConfig1 = case MemoryBytes of
|
||||||
0 ->
|
0 ->
|
||||||
@ -425,7 +468,7 @@ build_resources(#'ContainerSpec'{resources = #'ResourceLimits'{
|
|||||||
HostConfig3#{<<"CpuShares">> => CpuShares}
|
HostConfig3#{<<"CpuShares">> => CpuShares}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_ulimits(#'ContainerSpec'{ulimits = Ulimits}) ->
|
build_ulimits(Ulimits) when is_list(Ulimits) ->
|
||||||
case Ulimits of
|
case Ulimits of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
@ -437,7 +480,7 @@ build_ulimits(#'ContainerSpec'{ulimits = Ulimits}) ->
|
|||||||
} || #'Ulimit'{name = Name, soft = Soft, hard = Hard} <- Ulimits]}
|
} || #'Ulimit'{name = Name, soft = Soft, hard = Hard} <- Ulimits]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_sysctls(#'ContainerSpec'{sysctls = Sysctls}) ->
|
build_sysctls(Sysctls) when is_list(Sysctls) ->
|
||||||
case Sysctls of
|
case Sysctls of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
@ -445,16 +488,15 @@ build_sysctls(#'ContainerSpec'{sysctls = Sysctls}) ->
|
|||||||
#{<<"Sysctls">> => maps:from_list([{to_binary(Key), to_binary(Value)} || {Key, Value} <- Sysctls])}
|
#{<<"Sysctls">> => maps:from_list([{to_binary(Key), to_binary(Value)} || {Key, Value} <- Sysctls])}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_tmpfs(#'ContainerSpec'{tmpfs = Tmpfs}) ->
|
build_tmpfs(Tmpfs) when is_list(Tmpfs) ->
|
||||||
case Tmpfs of
|
case Tmpfs of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
_ ->
|
_ ->
|
||||||
#{<<"Tmpfs">> => maps:from_list([{to_binary(Path), to_binary(Options)} ||
|
#{<<"Tmpfs">> => maps:from_list([{to_binary(Path), to_binary(Options)} || {Path, Options} <- Tmpfs])}
|
||||||
#'TmpfsMount'{path = Path, options = Options} <- Tmpfs])}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
build_extra_hosts(#'ContainerSpec'{extra_hosts = Hosts}) ->
|
build_extra_hosts(Hosts) when is_list(Hosts) ->
|
||||||
case Hosts of
|
case Hosts of
|
||||||
[] ->
|
[] ->
|
||||||
#{};
|
#{};
|
||||||
@ -467,7 +509,7 @@ display_options(Options) when is_map(Options) ->
|
|||||||
logger:debug("deploy options: ~p", [jiffy:encode(Options, [force_utf8])]),
|
logger:debug("deploy options: ~p", [jiffy:encode(Options, [force_utf8])]),
|
||||||
lists:foreach(fun({K, V}) -> logger:debug("~p => ~p", [K, V]) end, maps:to_list(Options)).
|
lists:foreach(fun({K, V}) -> logger:debug("~p => ~p", [K, V]) end, maps:to_list(Options)).
|
||||||
|
|
||||||
normalize_expose_port(#'PortExpose'{container_port = Port, protocol = Protocol}) ->
|
normalize_expose_port(#'DockerExposedPort'{container_port = Port, protocol = Protocol}) ->
|
||||||
PortBin = integer_to_binary(Port),
|
PortBin = integer_to_binary(Port),
|
||||||
ProtocolBin = to_binary(Protocol),
|
ProtocolBin = to_binary(Protocol),
|
||||||
case ProtocolBin of
|
case ProtocolBin of
|
||||||
@ -484,15 +526,14 @@ device_permissions(<<>>) ->
|
|||||||
device_permissions(Permissions) ->
|
device_permissions(Permissions) ->
|
||||||
to_binary(Permissions).
|
to_binary(Permissions).
|
||||||
|
|
||||||
volume_bind(#'VolumeBind'{host_path = HostPath, container_path = ContainerPath, read_only = ReadOnly}) ->
|
add_unique_front([], List) ->
|
||||||
HostPathBin = to_binary(HostPath),
|
List;
|
||||||
ContainerPathBin = to_binary(ContainerPath),
|
add_unique_front([Item | Rest], List) ->
|
||||||
case to_bool(ReadOnly) of
|
NList = case lists:member(Item, List) of
|
||||||
true ->
|
true -> List;
|
||||||
<<HostPathBin/binary, ":", ContainerPathBin/binary, ":ro">>;
|
false -> [Item | List]
|
||||||
false ->
|
end,
|
||||||
<<HostPathBin/binary, ":", ContainerPathBin/binary>>
|
add_unique_front(Rest, NList).
|
||||||
end.
|
|
||||||
|
|
||||||
build_stop_container_url(ContainerName, 0) ->
|
build_stop_container_url(ContainerName, 0) ->
|
||||||
lists:flatten(io_lib:format("/containers/~s/stop", [binary_to_list(ContainerName)]));
|
lists:flatten(io_lib:format("/containers/~s/stop", [binary_to_list(ContainerName)]));
|
||||||
|
|||||||
@ -45,7 +45,7 @@ start_monitor(TaskId, ContainerDir, Params)
|
|||||||
-spec deploy(TaskId :: integer(), ContainerDir :: string(), Params :: message_pb:'ContainerDeployParams'()) -> no_return().
|
-spec deploy(TaskId :: integer(), ContainerDir :: string(), Params :: message_pb:'ContainerDeployParams'()) -> no_return().
|
||||||
deploy(TaskId, ContainerDir, Params = #'ContainerDeployParams'{
|
deploy(TaskId, ContainerDir, Params = #'ContainerDeployParams'{
|
||||||
container_name = ContainerName,
|
container_name = ContainerName,
|
||||||
spec = #'ContainerSpec'{image = Image0}
|
create = #'DockerCreateOptions'{config = #'DockerContainerConfig'{image = Image0}}
|
||||||
}) when is_integer(TaskId), is_list(ContainerDir) ->
|
}) when is_integer(TaskId), is_list(ContainerDir) ->
|
||||||
report_task_event(TaskId, <<"info">>, <<"开始部署容器:"/utf8, ContainerName/binary>>),
|
report_task_event(TaskId, <<"info">>, <<"开始部署容器:"/utf8, ContainerName/binary>>),
|
||||||
try
|
try
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -27,75 +27,84 @@ test_commands() ->
|
|||||||
test_create_container() ->
|
test_create_container() ->
|
||||||
Params = #'ContainerDeployParams'{
|
Params = #'ContainerDeployParams'{
|
||||||
container_name = <<"my_nginx_new1">>,
|
container_name = <<"my_nginx_new1">>,
|
||||||
spec = #'ContainerSpec'{
|
create = #'DockerCreateOptions'{
|
||||||
image = <<"docker.1ms.run/library/nginx:latest">>,
|
config = #'DockerContainerConfig'{
|
||||||
command = [
|
image = <<"docker.1ms.run/library/nginx:latest">>,
|
||||||
<<"nginx">>,
|
cmd = [
|
||||||
<<"-g">>,
|
<<"nginx">>,
|
||||||
<<"daemon off;">>
|
<<"-g">>,
|
||||||
],
|
<<"daemon off;">>
|
||||||
entrypoint = [
|
],
|
||||||
<<"/docker-entrypoint.sh">>
|
entrypoint = [
|
||||||
],
|
<<"/docker-entrypoint.sh">>
|
||||||
env = [
|
],
|
||||||
<<"ENV1=val1">>,
|
env = [
|
||||||
<<"ENV2=val2">>
|
<<"ENV1=val1">>,
|
||||||
],
|
<<"ENV2=val2">>
|
||||||
expose = [
|
],
|
||||||
#'PortExpose'{container_port = 80, protocol = <<"tcp">>},
|
volumes = [
|
||||||
#'PortExpose'{container_port = 443, protocol = <<"tcp">>}
|
<<"/data">>,
|
||||||
],
|
<<"/var/log">>
|
||||||
volumes = [
|
],
|
||||||
#'VolumeBind'{host_path = <<"/host/data">>, container_path = <<"/data">>},
|
labels = [
|
||||||
#'VolumeBind'{host_path = <<"/host/log">>, container_path = <<"/var/log">>}
|
{<<"role">>, <<"web">>},
|
||||||
],
|
{<<"env">>, <<"prod">>}
|
||||||
networks = [
|
],
|
||||||
<<"mynet">>
|
user = <<"www-data">>,
|
||||||
],
|
working_dir = <<"/app">>,
|
||||||
labels = [
|
hostname = <<"myhost">>,
|
||||||
{<<"role">>, <<"web">>},
|
exposed_ports = [
|
||||||
{<<"env">>, <<"prod">>}
|
#'DockerExposedPort'{container_port = 80, protocol = <<"tcp">>},
|
||||||
],
|
#'DockerExposedPort'{container_port = 443, protocol = <<"tcp">>}
|
||||||
restart = #'RestartPolicy'{name = <<"always">>},
|
],
|
||||||
user = <<"www-data">>,
|
healthcheck = #'Healthcheck'{
|
||||||
working_dir = <<"/app">>,
|
test = [
|
||||||
hostname = <<"myhost">>,
|
<<"CMD-SHELL">>,
|
||||||
privileged = true,
|
<<"curl -f http://localhost || exit 1">>
|
||||||
cap_add = [
|
],
|
||||||
<<"NET_ADMIN">>
|
interval_ns = 30000000000,
|
||||||
],
|
timeout_ns = 10000000000,
|
||||||
cap_drop = [
|
retries = 3
|
||||||
<<"MKNOD">>
|
}
|
||||||
],
|
|
||||||
devices = [
|
|
||||||
#'DeviceMapping'{host_path = <<"/dev/snd">>, container_path = <<"/dev/snd">>}
|
|
||||||
],
|
|
||||||
resources = #'ResourceLimits'{
|
|
||||||
memory_bytes = 512 * 1024 * 1024,
|
|
||||||
memory_reservation_bytes = 256 * 1024 * 1024,
|
|
||||||
cpu_shares = 512,
|
|
||||||
nano_cpus = 1500000000
|
|
||||||
},
|
},
|
||||||
ulimits = [
|
host_config = #'DockerHostConfig'{
|
||||||
#'Ulimit'{name = <<"nofile">>, soft = 1024, hard = 2048}
|
binds = [
|
||||||
],
|
<<"/host/data:/data">>,
|
||||||
sysctls = [
|
<<"/host/log:/var/log">>
|
||||||
{<<"net.ipv4.ip_forward">>, <<"1">>}
|
],
|
||||||
],
|
network_mode = <<"bridge">>,
|
||||||
tmpfs = [
|
restart_policy = #'RestartPolicy'{name = <<"always">>},
|
||||||
#'TmpfsMount'{path = <<"/tmp">>}
|
privileged = true,
|
||||||
],
|
cap_add = [
|
||||||
extra_hosts = [
|
<<"NET_ADMIN">>
|
||||||
<<"host1:192.168.0.1">>
|
],
|
||||||
],
|
cap_drop = [
|
||||||
healthcheck = #'Healthcheck'{
|
<<"MKNOD">>
|
||||||
test = [
|
],
|
||||||
<<"CMD-SHELL">>,
|
devices = [
|
||||||
<<"curl -f http://localhost || exit 1">>
|
#'DeviceMapping'{host_path = <<"/dev/snd">>, container_path = <<"/dev/snd">>}
|
||||||
],
|
],
|
||||||
interval_ns = 30000000000,
|
memory = 512 * 1024 * 1024,
|
||||||
timeout_ns = 10000000000,
|
memory_reservation = 256 * 1024 * 1024,
|
||||||
retries = 3
|
cpu_shares = 512,
|
||||||
|
nano_cpus = 1500000000,
|
||||||
|
ulimits = [
|
||||||
|
#'Ulimit'{name = <<"nofile">>, soft = 1024, hard = 2048}
|
||||||
|
],
|
||||||
|
sysctls = [
|
||||||
|
{<<"net.ipv4.ip_forward">>, <<"1">>}
|
||||||
|
],
|
||||||
|
tmpfs = [
|
||||||
|
{<<"/tmp">>, <<>>}
|
||||||
|
],
|
||||||
|
extra_hosts = [
|
||||||
|
<<"host1:192.168.0.1">>
|
||||||
|
]
|
||||||
|
},
|
||||||
|
networking_config = #'DockerNetworkingConfig'{
|
||||||
|
endpoints = [
|
||||||
|
#'DockerNetworkEndpoint'{name = <<"mynet">>}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user