class Devkitkat::Service::Driver::Docker::Container

Constants

ROOT_IN_CONTAINER

Attributes

container[R]

Public Instance Methods

exec(cmds, params = {}, &block) click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 36
def exec(cmds, params = {}, &block)
  params.merge!(user: user_name)
  safe_exec(cmds, params, &block)
end
exec_as_root(cmds, params = {}, &block) click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 41
def exec_as_root(cmds, params = {}, &block)
  safe_exec(cmds, params, &block)
end
interactive_shell(cmd) click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 45
def interactive_shell(cmd)
  # container.exec([new_path], tty: true, stdin: STDIN) { |stream, chunk| print "#{stream}" }
  Kernel.exec('docker', 'exec', '-ti', '--user', user_name, name, cmd)
end
start() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 12
def start
  @container = find

  if command.interactive?
    raise 'Container has not started yet for interactive session' unless @container
    return
  end

  if @container
    container.restart
  else
    @container = create
    container.start
    create_host_user
  end
end
stop() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 29
def stop
  return if command.interactive?
  raise 'Container has not started yet' unless container

  container.stop
end

Private Instance Methods

all_mounts() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 114
def all_mounts
  config.all_services.map do |service_name|
    service = Service.new(service_name, config, command)

    FileUtils.mkdir_p(service.dir)

    if self.service.name == service_name || service.system? || allowed_by_extra_write_accesses?(service)
      "#{service.dir}:#{ROOT_IN_CONTAINER}/services/#{service.name}"
    else
      "#{service.dir}:#{ROOT_IN_CONTAINER}/services/#{service.name}:ro"
    end
  end.append('/var/run/docker.sock:/var/run/docker.sock')
end
allowed_by_extra_write_accesses?(service) click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 128
def allowed_by_extra_write_accesses?(service)
  config.machine_extra_write_accesses&.any? do |access|
    from, _, to = access.split(':')
    self.service.name == from && service.name == to
  end
end
create() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 77
def create
  ::Docker::Container.create(create_parameter)
end
create_host_user() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 156
def create_host_user
  prepare!(['addgroup', '--gid', group_id, user_name])

  prepare!(['adduser',
    '--uid', user_id,
    '--gid', group_id,
    '--shell', '/bin/bash',
    '--home', ROOT_IN_CONTAINER,
    '--gecos', '',
    '--disabled-password',
    user_name])

  prepare!(['chown', "#{user_name}:#{user_name}", ROOT_IN_CONTAINER])
  prepare!(['chown', '-R', "#{user_name}:#{user_name}", "#{ROOT_IN_CONTAINER}/services/#{service.name}"])
  prepare!(['usermod', '-aG', 'docker', user_name])
  prepare!(['groupmod', '-g', docker_group_id, 'docker'])
end
create_parameter() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 81
def create_parameter
  params = {
    'Cmd' => %w[tail -f],
    'Image' => image,
    'name' => name,
    'HostConfig' => {
      'Binds' => all_mounts,
      'Privileged' => true
    }
  }

  if service.port
    params.deep_merge!(
      'ExposedPorts' => { "#{service.port}/tcp" => {} },
      'HostConfig' => {
        'PortBindings' => {
          "#{service.port}/tcp" => [{ 'HostPort' => service.port.to_s }]
        }
      }
    )
  end

  if config.machine_extra_hosts
    params.deep_merge!('HostConfig' => { 'ExtraHosts' => config.machine_extra_hosts })
  end

  if config.machine_network_mode
    params.deep_merge!('HostConfig' => { 'NetworkMode' => config.machine_network_mode })
  end

  params
end
docker_group_id() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 148
def docker_group_id
  @docker_group_id ||= `getent group docker | awk -F: '{ printf $3 }'`
end
find() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 71
def find
  ::Docker::Container.get(name)
rescue ::Docker::Error::NotFoundError
  nil
end
group_id() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 144
def group_id
  @group_id ||= `id -u`.delete("\n")
end
image() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 67
def image
  config.machine_image
end
name() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 135
def name
  @name ||=
    "#{config.application}-#{service.name}-#{Digest::SHA1.hexdigest(command.kit_root)[8..12]}"
end
prepare!(cmds, params = {}) click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 174
def prepare!(cmds, params = {})
  unless exec_as_root(cmds, params)
    raise Driver::Base::PreparationError, "Failed to execute command in container. cmds: #{cmds}"
  end
end
safe_exec(cmds, params, &block) click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 52
def safe_exec(cmds, params, &block)
  params.merge!(wait: 604800) # Default timeout is 1 minute, so setting 1 week instead
  stdout_messages, stderr_messages, exit_code =
    container.exec(cmds, params, &block)

  if exit_code != 0 || command.debug?
    puts "#{self.class.name} - #{__callee__}: stdout_messages: #{stdout_messages} stderr_messages: #{stderr_messages} exit_code: #{exit_code}"
  end

  exit_code == 0 ? true : false
rescue ::Docker::Error::ConflictError => e
  puts "#{self.class.name} - #{__callee__}: #{e.message}"
  false
end
user_id() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 152
def user_id
  @user_id ||= `id -g`
end
user_name() click to toggle source
# File lib/devkitkat/service/driver/docker/container.rb, line 140
def user_name
  'devkitkat'
end