docusaurus
This commit is contained in:
@@ -37,20 +37,6 @@ pub mut:
|
||||
command string
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct DockerContainerCreateArgs {
|
||||
name string
|
||||
hostname string
|
||||
forwarded_ports []string // ["80:9000/tcp", "1000, 10000/udp"]
|
||||
mounted_volumes []string // ["/root:/root", ]
|
||||
env map[string]string // map of environment variables that will be passed to the container
|
||||
privileged bool
|
||||
remove_when_done bool = true // remove the container when it shuts down
|
||||
pub mut:
|
||||
image_repo string
|
||||
image_tag string
|
||||
command string = '/bin/bash'
|
||||
}
|
||||
|
||||
// create/start container (first need to get a dockercontainer before we can start)
|
||||
pub fn (mut container DockerContainer) start() ! {
|
||||
|
||||
@@ -3,48 +3,146 @@ module docker
|
||||
import freeflowuniverse.herolib.osal { exec }
|
||||
import freeflowuniverse.herolib.virt.utils
|
||||
|
||||
|
||||
@[params]
|
||||
pub struct DockerContainerCreateArgs {
|
||||
pub mut:
|
||||
name string
|
||||
hostname string
|
||||
forwarded_ports []string // ["80:9000/tcp", "1000, 10000/udp"]
|
||||
mounted_volumes []string // ["/root:/root", ]
|
||||
env map[string]string // map of environment variables that will be passed to the container
|
||||
privileged bool
|
||||
remove_when_done bool = true // remove the container when it shuts down
|
||||
image_repo string
|
||||
image_tag string
|
||||
command string = '/bin/bash'
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut e DockerEngine) container_create(args DockerContainerCreateArgs) !&DockerContainer {
|
||||
// Validate required parameters
|
||||
if args.name.trim_space() == '' {
|
||||
return error('Container name cannot be empty')
|
||||
}
|
||||
|
||||
// Set default hostname if not provided
|
||||
mut hostname := args.hostname
|
||||
if hostname.trim_space() == '' {
|
||||
hostname = args.name.replace('_', '-')
|
||||
}
|
||||
|
||||
mut ports := ''
|
||||
mut mounts := ''
|
||||
mut env := ''
|
||||
mut command := args.command
|
||||
|
||||
// Build environment variables string with proper spacing
|
||||
for var, value in args.env {
|
||||
env += '-e ${var}="${value}"'
|
||||
if env != '' {
|
||||
env += ' '
|
||||
}
|
||||
env += '-e "${var}=${value}"'
|
||||
}
|
||||
|
||||
// Build ports string
|
||||
for port in args.forwarded_ports {
|
||||
ports = ports + '-p ${port} '
|
||||
if ports != '' {
|
||||
ports += ' '
|
||||
}
|
||||
ports += '-p ${port}'
|
||||
}
|
||||
|
||||
// Build mounts string
|
||||
for mount in args.mounted_volumes {
|
||||
mounts += '-v ${mount} '
|
||||
if mounts != '' {
|
||||
mounts += ' '
|
||||
}
|
||||
mounts += '-v ${mount}'
|
||||
}
|
||||
mut image := '${args.image_repo}'
|
||||
|
||||
// Build image string
|
||||
mut image := args.image_repo
|
||||
if args.image_tag != '' {
|
||||
image = image + ':${args.image_tag}'
|
||||
image += ':${args.image_tag}'
|
||||
} else {
|
||||
// Check if image exists with 'local' tag first
|
||||
mut local_check := exec(cmd: 'docker images ${args.image_repo}:local -q',debug:true)!
|
||||
if local_check.output != '' {
|
||||
image += ':local'
|
||||
} else {
|
||||
// Default to latest if no tag specified
|
||||
image += ':latest'
|
||||
}
|
||||
}
|
||||
|
||||
// Set default image and command for threefold
|
||||
if image == 'threefold' || image == 'threefold:latest' || image == '' {
|
||||
image = 'threefoldtech/grid3_ubuntu_dev'
|
||||
command = '/usr/local/bin/boot.sh'
|
||||
}
|
||||
|
||||
// Verify image exists locally
|
||||
mut image_check := exec(cmd: 'docker images ${image} -q')!
|
||||
if image_check.output == '' {
|
||||
return error('Docker image not found: ${image}. Please ensure the image exists locally or can be pulled from a registry.')
|
||||
}
|
||||
|
||||
privileged := if args.privileged { '--privileged' } else { '' }
|
||||
|
||||
// if forwarded ports passed in the args not containing mapping tp ssh (22) create one
|
||||
// Add SSH port if not present
|
||||
if !utils.contains_ssh_port(args.forwarded_ports) {
|
||||
// find random free port in the node
|
||||
mut port := e.get_free_port() or { panic('No free port.') }
|
||||
mut port := e.get_free_port() or { return error('No free port available for SSH') }
|
||||
if ports != '' {
|
||||
ports += ' '
|
||||
}
|
||||
ports += '-p ${port}:22/tcp'
|
||||
}
|
||||
|
||||
exec(
|
||||
cmd: 'docker run --hostname ${args.hostname} ${privileged} --sysctl net.ipv6.conf.all.disable_ipv6=0 --name ${args.name} ${ports} ${env} ${mounts} -d -t ${image} ${command}'
|
||||
)!
|
||||
// Have to reload the containers as container_get works from memory
|
||||
e.containers_load()!
|
||||
mut container := e.container_get(name: args.name)!
|
||||
// Construct docker run command with proper spacing and escaping
|
||||
mut mycmd := 'docker run'
|
||||
if hostname != '' {
|
||||
mycmd += ' --hostname "${hostname}"'
|
||||
}
|
||||
if privileged != '' {
|
||||
mycmd += ' ${privileged}'
|
||||
}
|
||||
mycmd += ' --sysctl net.ipv6.conf.all.disable_ipv6=0'
|
||||
mycmd += ' --name "${args.name}"'
|
||||
if ports != '' {
|
||||
mycmd += ' ${ports}'
|
||||
}
|
||||
if env != '' {
|
||||
mycmd += ' ${env}'
|
||||
}
|
||||
if mounts != '' {
|
||||
mycmd += ' ${mounts}'
|
||||
}
|
||||
mycmd += ' -d -t ${image}'
|
||||
if command != '' {
|
||||
mycmd += ' ${command}'
|
||||
}
|
||||
// Execute docker run command
|
||||
exec(cmd: mycmd) or {
|
||||
return error('Failed to create Docker container:
|
||||
Command: ${mycmd}
|
||||
Error: ${err}
|
||||
Possible causes:
|
||||
- Invalid image name or tag
|
||||
- Container name already in use
|
||||
- Port conflicts
|
||||
- Insufficient permissions
|
||||
Please check the error message and try again.')
|
||||
}
|
||||
|
||||
// Verify container was created successfully
|
||||
e.containers_load() or {
|
||||
return error('Container created but failed to reload container list: ${err}')
|
||||
}
|
||||
|
||||
mut container := e.container_get(name: args.name) or {
|
||||
return error('Container created but not found in container list. This may indicate the container failed to start properly. Check container logs with: docker logs ${args.name}')
|
||||
}
|
||||
|
||||
return container
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user