Compare commits
16 Commits
77935b49e8
...
master
Author | SHA1 | Date | |
---|---|---|---|
911ffe1c92 | |||
f43ac055c2 | |||
2e16523810 | |||
d7052998c8 | |||
488dedb74e | |||
9340dbe720 | |||
556b9d6b75 | |||
6c48e92378 | |||
84aaf451f7 | |||
6a266323bf | |||
0b334ea461 | |||
633ef98fab | |||
42c65b9783 | |||
b1878aef1b | |||
71fe46e881 | |||
d0adb3b0ed |
47
README.md
47
README.md
@@ -17,30 +17,40 @@ Otherworld creates a persistent Docker container running your choice of GNU/Linu
|
|||||||
## Arguments
|
## Arguments
|
||||||
These are arguments that go between `otherworld` and the command.
|
These are arguments that go between `otherworld` and the command.
|
||||||
|
|
||||||
### --container=<container>
|
### Creation Options
|
||||||
Name to assign to container (default: `otherworld_$USER`)
|
|
||||||
|
|
||||||
### --image=<image>
|
#### --image=<image>
|
||||||
Image to create the container with (default: `debian:stable`)
|
Image to create the container with (default: `image_$CONTAINER_NAME`, or `debian:stable` if that image does not exist)
|
||||||
|
|
||||||
### --sudo
|
#### --build=<path>
|
||||||
Runs command as root, instead of current user.
|
|
||||||
|
|
||||||
### --rm
|
|
||||||
Removes the specified container.
|
|
||||||
|
|
||||||
### --commit
|
|
||||||
Commits the container to an image named `image_$CONTAINER_NAME`.
|
|
||||||
|
|
||||||
### --build=<path>
|
|
||||||
Path to build context to build the image from. This overrides `--image`/`OW_IMAGE`. The resulting image is named `image_$CONTAINER_NAME`
|
Path to build context to build the image from. This overrides `--image`/`OW_IMAGE`. The resulting image is named `image_$CONTAINER_NAME`
|
||||||
|
|
||||||
### --volume=<volume>
|
#### --volume=<volume>
|
||||||
Volume to map to the container. `~` is expanded automatically. If the directory exists in the user's home directory it will be created to ensure it has the correct ownership and permissions.
|
A volume to mount in the container. `~` is expanded automatically. If the directory exists in the user's home directory it will be created to ensure it has the correct ownership and permissions.
|
||||||
|
|
||||||
### --env=<key>=<value>
|
#### --container=<container>
|
||||||
|
Name to assign to container (default: `otherworld_$USER`)
|
||||||
|
|
||||||
|
### Command Options
|
||||||
|
#### --env=<key>=<value>
|
||||||
Set the environment variable `key` to `value` in the command. **Note that this does not set environment variables in the container itself**.
|
Set the environment variable `key` to `value` in the command. **Note that this does not set environment variables in the container itself**.
|
||||||
|
|
||||||
|
#### --sudo
|
||||||
|
Runs command as root, instead of current user.
|
||||||
|
|
||||||
|
#### --cd/--cd=<directory>
|
||||||
|
Runs command in the specified directory, or current directory by default. If the container is being created, specified directory is added to list of volumes to mount. Otherwise, if the specified directory does not exist in the container, an error is raised.
|
||||||
|
|
||||||
|
### Container manipulation commands
|
||||||
|
#### --rm
|
||||||
|
Removes the otherworld container.
|
||||||
|
|
||||||
|
#### --rmi
|
||||||
|
Removes image generated by the `otherworld` script (`image_$CONTAINER_NAME`)
|
||||||
|
|
||||||
|
#### --commit
|
||||||
|
Commits the container to an image named `image_$CONTAINER_NAME`.
|
||||||
|
|
||||||
## Environment variables
|
## Environment variables
|
||||||
### OW_IMAGE
|
### OW_IMAGE
|
||||||
Image to create the container with (default: `debian:stable`)
|
Image to create the container with (default: `debian:stable`)
|
||||||
@@ -48,5 +58,8 @@ Image to create the container with (default: `debian:stable`)
|
|||||||
### OW_CONTAINER
|
### OW_CONTAINER
|
||||||
Name to assign to container (default: `otherworld_$USER`)
|
Name to assign to container (default: `otherworld_$USER`)
|
||||||
|
|
||||||
|
## Config Files
|
||||||
|
Otherworld will look for config files named `.otherworld` in the current directory and all ancestor directories. Config files are Python scripts that can access and redefine the following variables: `command`, `user`, `uid`, `command_user`, `image_name`, `container_name`, `build_path`, `command_workdir`, `user_volumes`, `pull`, `command_env`. Config files are loaded in descending order (e.g. so `~/.otherworld` is loaded before `~/Projects/.otherworld`) and before command line arguments are processed. Additional variables available are `cwd` (the current directory), `config_file` (path to current configuration file) and `config_file_dir` (parent directory of config file)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html) or later
|
[GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html) or later
|
||||||
|
318
otherworld
Normal file → Executable file
318
otherworld
Normal file → Executable file
@@ -7,7 +7,10 @@ import sys
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
CONTAINER_NAME = "otherworld"
|
CONTAINER_NAME = "otherworld"
|
||||||
IMAGE_NAME = "debian:stable"
|
DEFAULT_IMAGE_NAME = "debian:stable"
|
||||||
|
OTHERWORLD_LABEL = "otherworldowner"
|
||||||
|
|
||||||
|
OTHERWORLD_CONFIG = ".otherworld"
|
||||||
|
|
||||||
def create_x11_mapping ():
|
def create_x11_mapping ():
|
||||||
home = os.environ["HOME"]
|
home = os.environ["HOME"]
|
||||||
@@ -29,21 +32,37 @@ def create_x11_mapping ():
|
|||||||
"--shm-size", "2g",
|
"--shm-size", "2g",
|
||||||
"--privileged"]
|
"--privileged"]
|
||||||
|
|
||||||
DOCKER_CREATE_OPTIONS = ["-t"] + create_x11_mapping()
|
DOCKER_CREATE_OPTIONS = ["-t"]
|
||||||
USER_VOLUMES = ["~/otherworld"]
|
USER_VOLUMES = ["~/otherworld"]
|
||||||
BACKGROUND_COMMAND = None
|
BACKGROUND_COMMAND = None
|
||||||
DEFAULT_COMMAND = ["bash"]
|
DEFAULT_COMMAND = ["bash"]
|
||||||
|
|
||||||
GENERATED_IMAGE_NAME_TEMPLATE = "image_{container_name}"
|
GENERATED_IMAGE_NAME_TEMPLATE = "image_{container_name}"
|
||||||
|
|
||||||
|
CREATE_USER_BOOTSTRAP_SCRIPT="""
|
||||||
|
chown {user} /home/{user}
|
||||||
|
chown {user} /home/{user}/.config
|
||||||
|
cd /home/{user}
|
||||||
|
cp -Rv /etc/skel .
|
||||||
|
chown -R {user} skel
|
||||||
|
mv skel/* skel/.* .
|
||||||
|
rm -rf skel
|
||||||
|
"""
|
||||||
|
|
||||||
def get_generated_image_name (container_name):
|
def get_generated_image_name (container_name):
|
||||||
return GENERATED_IMAGE_NAME_TEMPLATE.format(container_name=container_name)
|
return GENERATED_IMAGE_NAME_TEMPLATE.format(container_name=container_name)
|
||||||
|
|
||||||
def docker_inspect (container):
|
def docker_inspect (container):
|
||||||
return json.loads(check_output(["docker", "inspect", container]))
|
return json.loads(check_output(["docker", "inspect", container]))
|
||||||
|
|
||||||
def docker_create (image, container, options, command):
|
def docker_list_containers (filter_argument):
|
||||||
docker_command = ["docker", "create", "--name", container] + options + [image]
|
return check_output(["docker", "ps", "-a", "--filter", filter_argument, "--format", "{{.Names}}"]).decode().strip().split("\n")
|
||||||
|
|
||||||
|
def docker_create (image, container, options, command, labels={}):
|
||||||
|
docker_command = ["docker", "create", "--name", container] + options
|
||||||
|
if labels:
|
||||||
|
docker_command = docker_command + list(chain.from_iterable([["--label", f"{kv[0]}={kv[1]}"] for kv in labels.items()]))
|
||||||
|
docker_command.append(image)
|
||||||
if command:
|
if command:
|
||||||
docker_command = docker_command + command
|
docker_command = docker_command + command
|
||||||
call(docker_command)
|
call(docker_command)
|
||||||
@@ -56,13 +75,15 @@ def docker_create_user (container, user, uid=None):
|
|||||||
if uid is not None:
|
if uid is not None:
|
||||||
command = command + ["--uid", str(uid)]
|
command = command + ["--uid", str(uid)]
|
||||||
call(command)
|
call(command)
|
||||||
call(["docker", "exec", container, "chown", user, f"/home/{user}"])
|
call(["docker", "exec", container, "sh", "-c", CREATE_USER_BOOTSTRAP_SCRIPT.format(user=user)])
|
||||||
|
|
||||||
def docker_start (container):
|
def docker_start (container):
|
||||||
call(["docker", "start", container])
|
call(["docker", "start", container])
|
||||||
|
|
||||||
def docker_exec (container, command, user, env={}):
|
def docker_exec (container, command, user, env={}, tty=True, work_dir=None):
|
||||||
call(["docker", "exec", "--user", user, "-ti"] + \
|
call(["docker", "exec", "--user", user] + \
|
||||||
|
(["-ti" if tty else "-i"]) + \
|
||||||
|
(["--workdir", work_dir] if work_dir else []) + \
|
||||||
list(chain.from_iterable([["--env", f"{kv[0]}={kv[1]}"] for kv in env.items()])) + \
|
list(chain.from_iterable([["--env", f"{kv[0]}={kv[1]}"] for kv in env.items()])) + \
|
||||||
[container] + command)
|
[container] + command)
|
||||||
|
|
||||||
@@ -72,6 +93,12 @@ def docker_commit (container, image_name):
|
|||||||
def docker_rm (container):
|
def docker_rm (container):
|
||||||
call(["docker", "rm", "-f", container])
|
call(["docker", "rm", "-f", container])
|
||||||
|
|
||||||
|
def docker_restart (container):
|
||||||
|
call(["docker", "restart", container])
|
||||||
|
|
||||||
|
def docker_rmi (container):
|
||||||
|
call(["docker", "rmi", "-f", container])
|
||||||
|
|
||||||
def docker_build (build_path, options, image_name):
|
def docker_build (build_path, options, image_name):
|
||||||
check_call(["docker", "build"] + options + ["-t", image_name, build_path])
|
check_call(["docker", "build"] + options + ["-t", image_name, build_path])
|
||||||
return image_name
|
return image_name
|
||||||
@@ -81,7 +108,7 @@ def docker_pull (image_name):
|
|||||||
|
|
||||||
def resolve_build_path (build_path):
|
def resolve_build_path (build_path):
|
||||||
if build_path is not None and build_path.startswith("~/"):
|
if build_path is not None and build_path.startswith("~/"):
|
||||||
build_path = f"{os.environ['HOME']}/{build_path[1:]}"
|
build_path = f"{os.environ['HOME']}/{build_path[2:]}"
|
||||||
|
|
||||||
return build_path
|
return build_path
|
||||||
|
|
||||||
@@ -96,78 +123,197 @@ def expand_user_volumes (volumes):
|
|||||||
(source, target) = source.split(":")
|
(source, target) = source.split(":")
|
||||||
|
|
||||||
if source.startswith("~/"):
|
if source.startswith("~/"):
|
||||||
source = f"{outer_home}/{source[1:]}"
|
source = f"{outer_home}/{source[2:]}"
|
||||||
|
|
||||||
if source.startswith(outer_home) and not os.path.exists(source):
|
if source.startswith(outer_home) and not os.path.exists(source):
|
||||||
os.makedirs(source)
|
os.makedirs(source)
|
||||||
|
|
||||||
if target.startswith("~/"):
|
if target.startswith("~/"):
|
||||||
target = f"{inner_home}/{target[1:]}"
|
target = f"{inner_home}/{target[2:]}"
|
||||||
|
|
||||||
mappings = mappings + ["-v", f"{source}:{target}"]
|
mappings = mappings + ["-v", f"{source}:{target}"]
|
||||||
|
|
||||||
return mappings
|
return mappings
|
||||||
|
|
||||||
|
def parse_command_line (command, config=None):
|
||||||
|
if config is None:
|
||||||
|
config = {
|
||||||
|
"actions": [],
|
||||||
|
"user_volumes": [],
|
||||||
|
"command_env": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
while len(command) > 0:
|
||||||
|
arg = command[0]
|
||||||
|
if arg == "--quiet":
|
||||||
|
command = command[1:]
|
||||||
|
config['quiet'] = True
|
||||||
|
elif arg == "--notty":
|
||||||
|
command = command[1:]
|
||||||
|
config['tty'] = False
|
||||||
|
elif arg == "--rm":
|
||||||
|
config['actions'].append("rm")
|
||||||
|
command = command[1:]
|
||||||
|
elif arg == "--restart":
|
||||||
|
config['actions'].append("restart")
|
||||||
|
command = command[1:]
|
||||||
|
elif arg == "--rmi":
|
||||||
|
config['actions'].append("rmi")
|
||||||
|
command = command[1:]
|
||||||
|
elif arg == "--commit":
|
||||||
|
config['actions'].append("commit")
|
||||||
|
command = command[1:]
|
||||||
|
elif arg == "--sudo":
|
||||||
|
config['command_user'] = "root"
|
||||||
|
command = command[1:]
|
||||||
|
elif arg.startswith("--container="):
|
||||||
|
config['container_name'] = arg[len("--container="):]
|
||||||
|
command = command[1:]
|
||||||
|
elif arg.startswith("--image="):
|
||||||
|
config['image_name'] = arg[len("--image="):]
|
||||||
|
command = command[1:]
|
||||||
|
elif arg.startswith("--build="):
|
||||||
|
config['build_path'] = arg[len("--build="):]
|
||||||
|
command = command[1:]
|
||||||
|
elif arg.startswith("--volume="):
|
||||||
|
config['user_volumes'].append(arg[len("--volume="):])
|
||||||
|
command = command[1:]
|
||||||
|
elif arg.startswith("--env="):
|
||||||
|
env_pair = arg[len("--env="):]
|
||||||
|
(key, value) = env_pair.split("=", 1)
|
||||||
|
config['command_env'][key] = value
|
||||||
|
command = command[1:]
|
||||||
|
elif arg == "--cd":
|
||||||
|
config['command_workdir'] = os.getcwd()
|
||||||
|
command = command[1:]
|
||||||
|
elif arg.startswith("--cd="):
|
||||||
|
config['command_workdir'] = arg[len("--cd="):]
|
||||||
|
command = command[1:]
|
||||||
|
elif arg == "--pull":
|
||||||
|
command = command[1:]
|
||||||
|
config['pull'] = True
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return (config, command)
|
||||||
|
|
||||||
|
def find_config_files (config_names):
|
||||||
|
config_files = []
|
||||||
|
directory = os.path.abspath(os.getcwd())
|
||||||
|
while True:
|
||||||
|
for config_name in config_names:
|
||||||
|
config_file = os.path.join(directory, config_name)
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
config_files.append(config_file)
|
||||||
|
|
||||||
|
if directory == "/" or (not directory):
|
||||||
|
break
|
||||||
|
|
||||||
|
directory = os.path.dirname(directory)
|
||||||
|
config_files.reverse()
|
||||||
|
return config_files
|
||||||
|
|
||||||
|
def load_config_files (namespace, config_files):
|
||||||
|
config_keys = list(namespace.keys())
|
||||||
|
for config_file in config_files:
|
||||||
|
with open(config_file) as config_code:
|
||||||
|
namespace.update({
|
||||||
|
"config_file": config_file,
|
||||||
|
"config_file_dir": os.path.dirname(config_file)
|
||||||
|
})
|
||||||
|
exec(config_code.read(), {}, namespace)
|
||||||
|
return dict([item for item in namespace.items() if item[0] in config_keys])
|
||||||
|
|
||||||
|
def init_command_as_list (command):
|
||||||
|
if isinstance(command, str):
|
||||||
|
command = ["sh", "-c", command]
|
||||||
|
return command
|
||||||
|
|
||||||
|
# parse options and command from command line
|
||||||
|
(command_line_options, command) = parse_command_line(sys.argv[1:])
|
||||||
|
actions = command_line_options['actions']
|
||||||
|
|
||||||
|
quiet = command_line_options.get("quiet", False)
|
||||||
|
def log (message, *args, **kwargs):
|
||||||
|
if quiet:
|
||||||
|
return
|
||||||
|
print(">> {}".format(message.format(*args, **kwargs)))
|
||||||
|
|
||||||
|
tty = sys.stdout.isatty()
|
||||||
|
|
||||||
|
# default config
|
||||||
user = os.environ["USER"]
|
user = os.environ["USER"]
|
||||||
uid = int(check_output(["id", "-u"]).strip())
|
config = {
|
||||||
image_name = os.environ.get("OW_IMAGE", IMAGE_NAME)
|
"command": command,
|
||||||
container_name = os.environ.get("OW_CONTAINER", f"{CONTAINER_NAME}_{user}")
|
"user": user,
|
||||||
build_path = None
|
"uid": int(check_output(["id", "-u"]).strip()),
|
||||||
|
"command_user": user,
|
||||||
|
"image_name": os.environ.get("OW_IMAGE", None),
|
||||||
|
"container_name": command_line_options.get("container_name", os.environ.get("OW_CONTAINER", f"{CONTAINER_NAME}_{user}")),
|
||||||
|
"build_path": None,
|
||||||
|
"command_workdir": None,
|
||||||
|
"user_volumes": USER_VOLUMES,
|
||||||
|
"pull": False,
|
||||||
|
"command_env": {},
|
||||||
|
"cwd": os.getcwd(),
|
||||||
|
"tty": sys.stdout.isatty(),
|
||||||
|
"log": log,
|
||||||
|
"root_init_command": [],
|
||||||
|
"root_init_commmands": [],
|
||||||
|
"user_init_command": [],
|
||||||
|
"user_init_commands": [],
|
||||||
|
"docker_create_options": []
|
||||||
|
}
|
||||||
|
|
||||||
command = sys.argv[1:]
|
# load config from files
|
||||||
command_user = user
|
config_files = find_config_files([
|
||||||
user_volumes = USER_VOLUMES
|
OTHERWORLD_CONFIG,
|
||||||
pull = False
|
"{}{}".format(config['container_name'], OTHERWORLD_CONFIG)
|
||||||
|
])
|
||||||
|
|
||||||
command_env = {}
|
for config_file in config_files:
|
||||||
|
log("Loading config file {}", config_file)
|
||||||
|
|
||||||
quiet = False
|
config = load_config_files(config, config_files)
|
||||||
while len(command) > 0:
|
|
||||||
arg = command[0]
|
# apply config from command line
|
||||||
if arg == "--quiet":
|
for key, value in command_line_options.items():
|
||||||
command = command[1:]
|
if key == "user_volumes":
|
||||||
quiet = True
|
config['user_volumes'] = config['user_volumes'] + value
|
||||||
elif arg == "--rm":
|
elif key == "command_env":
|
||||||
if not quiet:
|
config['command_env'].update(value)
|
||||||
print(f">> Removing container: {container_name}")
|
|
||||||
docker_rm(container_name)
|
|
||||||
sys.exit(0)
|
|
||||||
elif arg == "--commit":
|
|
||||||
image_name = get_generated_image_name(container_name)
|
|
||||||
if not quiet:
|
|
||||||
print(f">> Committing container: {container_name} to image: {image_name}")
|
|
||||||
docker_commit(container_name, image_name)
|
|
||||||
sys.exit(0)
|
|
||||||
elif arg == "--sudo":
|
|
||||||
command_user = "root"
|
|
||||||
command = command[1:]
|
|
||||||
elif arg.startswith("--container="):
|
|
||||||
container_name = arg[len("--container="):]
|
|
||||||
command = command[1:]
|
|
||||||
elif arg.startswith("--image"):
|
|
||||||
image_name = get_generated_image_name(container_name)
|
|
||||||
command = command[1:]
|
|
||||||
elif arg.startswith("--image="):
|
|
||||||
image_name = arg[len("--image="):]
|
|
||||||
command = command[1:]
|
|
||||||
elif arg.startswith("--build="):
|
|
||||||
build_path = arg[len("--build="):]
|
|
||||||
command = command[1:]
|
|
||||||
elif arg.startswith("--volume="):
|
|
||||||
user_volumes.append(arg[len("--volume="):])
|
|
||||||
command = command[1:]
|
|
||||||
elif arg.startswith("--env="):
|
|
||||||
env_pair = arg[len("--env="):]
|
|
||||||
(key, value) = env_pair.split("=", 1)
|
|
||||||
command_env[key] = value
|
|
||||||
command = command[1:]
|
|
||||||
elif arg == "--pull":
|
|
||||||
command = command[1:]
|
|
||||||
pull = True
|
|
||||||
else:
|
else:
|
||||||
break
|
config[key] = value
|
||||||
|
|
||||||
if len(command) == 0:
|
# update local variables (FIXME: rewrite to avoid doing this)
|
||||||
|
locals().update(config)
|
||||||
|
|
||||||
|
if command_workdir:
|
||||||
|
user_volumes.append(command_workdir)
|
||||||
|
command_workdir = resolve_build_path(command_workdir)
|
||||||
|
|
||||||
|
if actions:
|
||||||
|
if "commit" in actions:
|
||||||
|
target_image_name = get_generated_image_name(container_name)
|
||||||
|
log("Committing container: {} to image: {}", container_name, target_image_name)
|
||||||
|
docker_commit(container_name, target_image_name)
|
||||||
|
|
||||||
|
if "restart" in actions:
|
||||||
|
log("Restarting container: {}", container_name)
|
||||||
|
docker_restart(container_name)
|
||||||
|
|
||||||
|
if "rm" in actions:
|
||||||
|
log("Removing container: {}", container_name)
|
||||||
|
docker_rm(container_name)
|
||||||
|
|
||||||
|
if "rmi" in actions:
|
||||||
|
target_image_name = get_generated_image_name(container_name)
|
||||||
|
log("Removing image: {}", target_image_name)
|
||||||
|
docker_rmi(target_image_name)
|
||||||
|
|
||||||
|
if not command:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if not command:
|
||||||
command = DEFAULT_COMMAND
|
command = DEFAULT_COMMAND
|
||||||
|
|
||||||
container = None
|
container = None
|
||||||
@@ -177,32 +323,50 @@ except Exception:
|
|||||||
build_path = resolve_build_path(build_path)
|
build_path = resolve_build_path(build_path)
|
||||||
if build_path is not None:
|
if build_path is not None:
|
||||||
image_name = docker_build(build_path, ["--pull"] if pull else [], get_generated_image_name(container_name))
|
image_name = docker_build(build_path, ["--pull"] if pull else [], get_generated_image_name(container_name))
|
||||||
elif pull:
|
else:
|
||||||
docker_pull(image_name)
|
if image_name is None:
|
||||||
|
image_name = get_generated_image_name(container_name)
|
||||||
|
try:
|
||||||
|
docker_inspect(image_name)
|
||||||
|
log("Using default otherworld image {}", image_name)
|
||||||
|
except Exception:
|
||||||
|
log("Default otherworld image {} not found, falling back to {}", image_name, DEFAULT_IMAGE_NAME)
|
||||||
|
image_name = DEFAULT_IMAGE_NAME
|
||||||
|
|
||||||
if not quiet:
|
if pull:
|
||||||
print(f">> Creating container: {container_name} (using image: {image_name})")
|
docker_pull(image_name)
|
||||||
|
|
||||||
|
log("Creating container: {} (using image: {})", container_name, image_name)
|
||||||
docker_create(
|
docker_create(
|
||||||
image_name,
|
image_name,
|
||||||
container_name,
|
container_name,
|
||||||
DOCKER_CREATE_OPTIONS + expand_user_volumes(user_volumes),
|
DOCKER_CREATE_OPTIONS + config.get("docker_create_options", []) + create_x11_mapping() + expand_user_volumes(user_volumes),
|
||||||
BACKGROUND_COMMAND
|
BACKGROUND_COMMAND, { OTHERWORLD_LABEL: user }
|
||||||
)
|
)
|
||||||
container = docker_inspect(container_name)[0]
|
container = docker_inspect(container_name)[0]
|
||||||
|
|
||||||
if not container["State"]["Running"]:
|
if not container["State"]["Running"]:
|
||||||
if not quiet:
|
log("Starting container: {}", container_name)
|
||||||
print(f">> Starting container: {container_name}")
|
|
||||||
docker_start(container_name)
|
docker_start(container_name)
|
||||||
container = docker_inspect(container_name)[0]
|
container = docker_inspect(container_name)[0]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
docker_get_user(container_name, user)
|
docker_get_user(container_name, user)
|
||||||
except Exception:
|
except Exception:
|
||||||
if not quiet:
|
log("Creating container user: {}", user)
|
||||||
print(f">> Creating container user: {user}")
|
|
||||||
docker_create_user(container_name, user, uid)
|
docker_create_user(container_name, user, uid)
|
||||||
|
|
||||||
if not quiet:
|
if config['root_init_command']:
|
||||||
print(f">> Welcome to {container_name} (IP {container['NetworkSettings']['IPAddress']})")
|
config['root_init_commands'].append(config['root_init_command'])
|
||||||
docker_exec(container_name, command, command_user, command_env)
|
|
||||||
|
for command in config['root_init_commands']:
|
||||||
|
docker_exec(container_name, init_command_as_list(command), "root", command_env, tty, "/home/{}".format(command_user))
|
||||||
|
|
||||||
|
if config['user_init_command']:
|
||||||
|
config['user_init_commands'].append(config['user_init_command'])
|
||||||
|
|
||||||
|
for command in config['user_init_commands']:
|
||||||
|
docker_exec(container_name, init_command_as_list(command), command_user, command_env, tty, "/home/{}".format(command_user))
|
||||||
|
|
||||||
|
log("Welcome to {} (IP {})", container_name, container['NetworkSettings']['IPAddress'])
|
||||||
|
docker_exec(container_name, command, command_user, command_env, tty, command_workdir)
|
||||||
|
Reference in New Issue
Block a user