fix docker create

This commit is contained in:
anlicheng 2026-04-21 11:23:16 +08:00
parent ecfbdae8f4
commit 6fc0e4277c
4 changed files with 1467 additions and 1430 deletions

View File

@ -106,51 +106,74 @@
-record('ContainerDeployParams',
{container_name = <<>> :: unicode:chardata() | undefined, % = 1, 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.
-ifndef('CONTAINERSPEC_PB_H').
-define('CONTAINERSPEC_PB_H', true).
-record('ContainerSpec',
-ifndef('DOCKERCREATEOPTIONS_PB_H').
-define('DOCKERCREATEOPTIONS_PB_H', true).
-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
command = [] :: [unicode:chardata()] | undefined, % = 2, repeated
cmd = [] :: [unicode:chardata()] | undefined, % = 2, repeated
entrypoint = [] :: [unicode:chardata()] | undefined, % = 3, repeated
env = [] :: [unicode:chardata()] | undefined, % = 4, repeated
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
working_dir = <<>> :: unicode:chardata() | undefined, % = 8, optional
hostname = <<>> :: unicode:chardata() | undefined, % = 9, optional
expose = [] :: [message_pb:'PortExpose'()] | undefined, % = 10, repeated
networks = [] :: [unicode:chardata()] | undefined, % = 11, repeated
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
exposed_ports = [] :: [message_pb:'DockerExposedPort'()] | undefined, % = 10, repeated
healthcheck = undefined :: message_pb:'Healthcheck'() | undefined % = 11, optional
}).
-endif.
-ifndef('VOLUMEBIND_PB_H').
-define('VOLUMEBIND_PB_H', true).
-record('VolumeBind',
{host_path = <<>> :: unicode:chardata() | undefined, % = 1, optional
container_path = <<>> :: unicode:chardata() | undefined, % = 2, optional
read_only = false :: boolean() | 0 | 1 | undefined % = 3, optional
-ifndef('DOCKERHOSTCONFIG_PB_H').
-define('DOCKERHOSTCONFIG_PB_H', true).
-record('DockerHostConfig',
{binds = [] :: [unicode:chardata()] | undefined, % = 1, repeated
network_mode = <<>> :: unicode:chardata() | undefined, % = 2, 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.
-ifndef('PORTEXPOSE_PB_H').
-define('PORTEXPOSE_PB_H', true).
-record('PortExpose',
-ifndef('DOCKERNETWORKINGCONFIG_PB_H').
-define('DOCKERNETWORKINGCONFIG_PB_H', true).
-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
protocol = <<>> :: unicode:chardata() | undefined % = 2, optional
}).
@ -183,16 +206,6 @@
}).
-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').
-define('ULIMIT_PB_H', true).
-record('Ulimit',
@ -202,14 +215,6 @@
}).
-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').
-define('AUTHREQUEST_PB_H', true).
-record('AuthRequest',

View File

@ -83,48 +83,56 @@ message ContainerRequest {
message ContainerDeployParams {
string container_name = 1;
string container_dir = 2;
ContainerSpec spec = 3;
DockerCreateOptions create = 3;
}
message ContainerSpec {
string image = 1;
repeated string command = 2;
repeated string entrypoint = 3;
message DockerCreateOptions {
DockerContainerConfig config = 1;
DockerHostConfig host_config = 2;
DockerNetworkingConfig networking_config = 3;
}
message DockerContainerConfig {
string image = 1;
repeated string cmd = 2;
repeated string entrypoint = 3;
repeated string env = 4;
map<string, string> labels = 5;
repeated VolumeBind volumes = 6;
repeated string volumes = 6;
string user = 7;
string working_dir = 8;
string hostname = 9;
repeated PortExpose expose = 10;
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;
repeated DockerExposedPort exposed_ports = 10;
Healthcheck healthcheck = 11;
}
message VolumeBind {
string host_path = 1;
string container_path = 2;
bool read_only = 3;
message DockerHostConfig {
repeated string binds = 1;
string network_mode = 2;
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;
string protocol = 2; // tcp / udp
}
@ -147,24 +155,12 @@ message DeviceMapping {
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 {
string name = 1;
uint64 soft = 2;
uint64 hard = 3;
}
message TmpfsMount {
string path = 1;
string options = 2;
}
message AuthRequest {
bytes uuid = 1;

View File

@ -209,26 +209,29 @@ check_type(_, _) ->
build_container_deploy_params(Config) when is_map(Config) ->
ContainerName = maps:get(<<"container_name">>, Config),
ContainerDir = maps:get(<<"container_dir">>, Config, <<>>),
Spec = build_container_spec(Config),
Create = build_docker_create_options(Config),
#'ContainerDeployParams'{
container_name = ContainerName,
container_dir = ContainerDir,
spec = Spec
create = Create
}.
-spec build_container_spec(Config :: map()) -> message_pb:'ContainerSpec'().
build_container_spec(Config) when is_map(Config) ->
Volumes = build_volume_binds(maps:get(<<"volumes">>, Config, [])),
Expose = build_port_exposes(maps:get(<<"expose">>, Config, [])),
Restart = build_restart_policy(maps:get(<<"restart">>, Config)),
Devices = build_device_mappings(maps:get(<<"devices">>, Config, [])),
Resources = build_resource_limits(Config),
Ulimits = build_ulimits(maps:get(<<"ulimits">>, Config, #{})),
Tmpfs = build_tmpfs_mounts(maps:get(<<"tmpfs">>, Config, [])),
-spec build_docker_create_options(Config :: map()) -> message_pb:'DockerCreateOptions'().
build_docker_create_options(Config) when is_map(Config) ->
#'DockerCreateOptions'{
config = build_docker_container_config(Config),
host_config = build_docker_host_config(Config),
networking_config = build_docker_networking_config(Config)
}.
-spec build_docker_container_config(Config :: map()) -> message_pb:'DockerContainerConfig'().
build_docker_container_config(Config) when is_map(Config) ->
Volumes = build_container_volumes(maps:get(<<"volumes">>, Config, [])),
ExposedPorts = build_exposed_ports(maps:get(<<"expose">>, Config, [])),
Healthcheck = build_healthcheck(maps:get(<<"healthcheck">>, Config, undefined)),
#'ContainerSpec'{
#'DockerContainerConfig'{
image = maps:get(<<"image">>, Config),
command = maps:get(<<"command">>, Config),
cmd = maps:get(<<"command">>, Config),
entrypoint = maps:get(<<"entrypoint">>, Config, []),
env = maps:get(<<"envs">>, Config, []),
labels = maps:to_list(maps:get(<<"labels">>, Config, #{})),
@ -236,22 +239,46 @@ build_container_spec(Config) when is_map(Config) ->
user = maps:get(<<"user">>, Config, <<>>),
working_dir = maps:get(<<"working_dir">>, Config, <<>>),
hostname = maps:get(<<"hostname">>, Config, <<>>),
expose = Expose,
networks = maps:get(<<"networks">>, Config, []),
exposed_ports = ExposedPorts,
healthcheck = Healthcheck
}.
-spec build_docker_host_config(Config :: map()) -> message_pb:'DockerHostConfig'().
build_docker_host_config(Config) when is_map(Config) ->
Binds = build_host_binds(maps:get(<<"volumes">>, Config, [])),
RestartPolicy = build_restart_policy(maps:get(<<"restart">>, Config)),
Devices = build_device_mappings(maps:get(<<"devices">>, Config, [])),
Ulimits = build_ulimits(maps:get(<<"ulimits">>, Config, #{})),
Tmpfs = build_tmpfs_options(maps:get(<<"tmpfs">>, Config, [])),
Memory = default_uint64(parse_optional_size_bytes(maps:get(<<"mem_limit">>, Config, undefined), <<"mem_limit">>)),
MemoryReservation = default_uint64(parse_optional_size_bytes(maps:get(<<"mem_reservation">>, Config, undefined), <<"mem_reservation">>)),
NanoCpus = default_uint64(parse_optional_nano_cpus(maps:get(<<"cpus">>, Config, undefined))),
CpuShares = default_uint64(maps:get(<<"cpu_shares">>, Config, undefined)),
#'DockerHostConfig'{
binds = Binds,
network_mode = maps:get(<<"network_mode">>, Config, <<>>),
healthcheck = Healthcheck,
restart = Restart,
restart_policy = RestartPolicy,
privileged = maps:get(<<"privileged">>, Config, false),
cap_add = maps:get(<<"cap_add">>, Config, []),
cap_drop = maps:get(<<"cap_drop">>, Config, []),
devices = Devices,
resources = Resources,
memory = Memory,
memory_reservation = MemoryReservation,
nano_cpus = NanoCpus,
cpu_shares = CpuShares,
ulimits = Ulimits,
tmpfs = Tmpfs,
sysctls = maps:to_list(maps:get(<<"sysctls">>, Config, #{})),
extra_hosts = maps:get(<<"extra_hosts">>, Config, [])
}.
-spec build_docker_networking_config(Config :: map()) -> message_pb:'DockerNetworkingConfig'().
build_docker_networking_config(Config) when is_map(Config) ->
Networks = maps:get(<<"networks">>, Config, []),
#'DockerNetworkingConfig'{
endpoints = [#'DockerNetworkEndpoint'{name = Network} || Network <- Networks]
}.
-spec build_restart_policy(binary()) -> message_pb:'RestartPolicy'().
build_restart_policy(Restart0) when is_binary(Restart0) ->
case binary:split(Restart0, <<":">>) of
@ -272,24 +299,6 @@ build_healthcheck(Healthcheck) when is_map(Healthcheck) ->
retries = maps:get(<<"retries">>, Healthcheck, 0)
}.
-spec build_resource_limits(map()) -> undefined | message_pb:'ResourceLimits'().
build_resource_limits(Config) when is_map(Config) ->
MemoryBytes = parse_optional_size_bytes(maps:get(<<"mem_limit">>, Config, undefined), <<"mem_limit">>),
ReservationBytes = parse_optional_size_bytes(maps:get(<<"mem_reservation">>, Config, undefined), <<"mem_reservation">>),
NanoCpus = parse_optional_nano_cpus(maps:get(<<"cpus">>, Config, undefined)),
CpuShares = maps:get(<<"cpu_shares">>, Config, undefined),
case {MemoryBytes, ReservationBytes, NanoCpus, CpuShares} of
{undefined, undefined, undefined, undefined} ->
undefined;
_ ->
#'ResourceLimits'{
memory_bytes = default_uint64(MemoryBytes),
memory_reservation_bytes = default_uint64(ReservationBytes),
nano_cpus = default_uint64(NanoCpus),
cpu_shares = default_uint64(CpuShares)
}
end.
-spec default_uint64(undefined | non_neg_integer()) -> non_neg_integer().
default_uint64(undefined) ->
0;
@ -304,32 +313,44 @@ parse_optional_nano_cpus(Cpus) when is_integer(Cpus), Cpus >= 0 ->
parse_optional_nano_cpus(Cpus) when is_float(Cpus), Cpus >= 0 ->
trunc(Cpus * 1000000000).
-spec build_volume_binds([binary()]) -> [message_pb:'VolumeBind'()].
build_volume_binds(VolumeSpecs) when is_list(VolumeSpecs) ->
[build_volume_bind(VolumeSpec) || VolumeSpec <- VolumeSpecs].
-spec build_container_volumes([binary()]) -> [binary()].
build_container_volumes(VolumeSpecs) when is_list(VolumeSpecs) ->
[ContainerPath || VolumeSpec <- VolumeSpecs, {_HostPath, ContainerPath, _ReadOnly} <- [parse_volume_spec(VolumeSpec)]].
-spec build_volume_bind(binary()) -> message_pb:'VolumeBind'().
build_volume_bind(VolumeSpec) when is_binary(VolumeSpec) ->
-spec build_host_binds([binary()]) -> [binary()].
build_host_binds(VolumeSpecs) when is_list(VolumeSpecs) ->
[volume_bind(HostPath, ContainerPath, ReadOnly) ||
VolumeSpec <- VolumeSpecs,
{HostPath, ContainerPath, ReadOnly} <- [parse_volume_spec(VolumeSpec)]].
-spec parse_volume_spec(binary()) -> {binary(), binary(), boolean()}.
parse_volume_spec(VolumeSpec) when is_binary(VolumeSpec) ->
case binary:split(VolumeSpec, <<":">>, [global]) of
[HostPath, ContainerPath] when HostPath =/= <<>>, ContainerPath =/= <<>> ->
#'VolumeBind'{host_path = HostPath, container_path = ContainerPath, read_only = false};
{HostPath, ContainerPath, false};
[HostPath, ContainerPath | Modes] when HostPath =/= <<>>, ContainerPath =/= <<>> ->
#'VolumeBind'{host_path = HostPath, container_path = ContainerPath, read_only = lists:member(<<"ro">>, Modes)};
{HostPath, ContainerPath, lists:member(<<"ro">>, Modes)};
_ ->
throw({error, <<"invalid volume binding">>})
end.
-spec build_port_exposes([binary()]) -> [message_pb:'PortExpose'()].
build_port_exposes(ExposeSpecs) when is_list(ExposeSpecs) ->
[build_port_expose(ExposeSpec) || ExposeSpec <- ExposeSpecs].
-spec volume_bind(binary(), binary(), boolean()) -> binary().
volume_bind(HostPath, ContainerPath, true) when is_binary(HostPath), is_binary(ContainerPath) ->
<<HostPath/binary, ":", ContainerPath/binary, ":ro">>;
volume_bind(HostPath, ContainerPath, false) when is_binary(HostPath), is_binary(ContainerPath) ->
<<HostPath/binary, ":", ContainerPath/binary>>.
-spec build_port_expose(binary()) -> message_pb:'PortExpose'().
build_port_expose(ExposeSpec) when is_binary(ExposeSpec) ->
-spec build_exposed_ports([binary()]) -> [message_pb:'DockerExposedPort'()].
build_exposed_ports(ExposeSpecs) when is_list(ExposeSpecs) ->
[build_exposed_port(ExposeSpec) || ExposeSpec <- ExposeSpecs].
-spec build_exposed_port(binary()) -> message_pb:'DockerExposedPort'().
build_exposed_port(ExposeSpec) when is_binary(ExposeSpec) ->
case binary:split(ExposeSpec, <<"/">>) of
[PortBin] ->
#'PortExpose'{container_port = parse_uint32(PortBin, <<"expose">>), protocol = <<"tcp">>};
#'DockerExposedPort'{container_port = parse_uint32(PortBin, <<"expose">>), protocol = <<"tcp">>};
[PortBin, Protocol] ->
#'PortExpose'{container_port = parse_uint32(PortBin, <<"expose">>), protocol = Protocol}
#'DockerExposedPort'{container_port = parse_uint32(PortBin, <<"expose">>), protocol = Protocol}
end.
-spec build_device_mappings([binary()]) -> [message_pb:'DeviceMapping'()].
@ -361,17 +382,17 @@ build_ulimit(Name, Value) when is_binary(Name), is_binary(Value) ->
#'Ulimit'{name = Name, soft = Limit, hard = Limit}
end.
-spec build_tmpfs_mounts([binary()]) -> [message_pb:'TmpfsMount'()].
build_tmpfs_mounts(TmpfsSpecs) when is_list(TmpfsSpecs) ->
[build_tmpfs_mount(TmpfsSpec) || TmpfsSpec <- TmpfsSpecs].
-spec build_tmpfs_options([binary()]) -> [{binary(), binary()}].
build_tmpfs_options(TmpfsSpecs) when is_list(TmpfsSpecs) ->
[build_tmpfs_option(TmpfsSpec) || TmpfsSpec <- TmpfsSpecs].
-spec build_tmpfs_mount(binary()) -> message_pb:'TmpfsMount'().
build_tmpfs_mount(TmpfsSpec) when is_binary(TmpfsSpec) ->
-spec build_tmpfs_option(binary()) -> {binary(), binary()}.
build_tmpfs_option(TmpfsSpec) when is_binary(TmpfsSpec) ->
case binary:split(TmpfsSpec, <<":">>) of
[Path] when Path =/= <<>> ->
#'TmpfsMount'{path = Path, options = <<>>};
{Path, <<>>};
[Path, Options] when Path =/= <<>> ->
#'TmpfsMount'{path = Path, options = Options};
{Path, Options};
_ ->
throw({error, <<"invalid tmpfs mount">>})
end.

File diff suppressed because it is too large Load Diff