2015-09-23 5 views
0

Я пытаюсь реализовать что-то в действии docker run и docker exec с использованием libcontainer.Libcontainer - Выполнение нескольких процессов в контейнере

Я был в состоянии создать контейнер и запустить процесс внутри нее с помощью следующего кода:

func Run(id string, s *specs.LinuxSpec, f *Factory) (int, error) { 
    ... 
    container, err := f.CreateContainer(id, config) 
    if err != nil { 
     return -1, err 
    } 

    process := newProcess(s.Process) 
    tty, err := newTty(s.Process.Terminal, process, rootuid) 
    defer tty.Close() 
    if err != nil { 
     return -1, err 
    } 

    defer func() { 
     if derr := Destroy(container); derr != nil { 
      err = derr 
     } 
    }() 

    handler := NewSignalHandler(tty) 
    defer handler.Close() 
    if err := container.Start(process); err != nil { 
     return -1, err 
    } 

    return handler.forward(process) 
} 

Это прекрасно работает (я считаю), но проблема возникает, когда я должен запустить другой процесс (es) внутри того же контейнера. Например, контейнер уже запущен (основной процесс выполняется в режиме переднего плана): Как я могу достичь того, что Docker позволяет вам делать с docker exec?

У меня есть следующий код:

func Exec(container libcontainer.Container, process *libcontainer.Process, onData func(data []byte), onErr func(err error)) (int, error) { 
    reader, writer := io.Pipe() 
    process.Stdin = os.Stdin 

    rootuid, err := container.Config().HostUID() 
    if err != nil { 
     return -1, err 
    } 

    tty, err := newTty(true, process, rootuid) 
    defer tty.Close() 
    if err != nil { 
     return -1, err 
    } 

    handler := NewSignalHandler(tty) 
    defer handler.Close() 

    // Redirect process output 
    process.Stdout = writer 
    process.Stderr = writer 

    // Todo: Fix this, it waits for the main process to exit before it starts 
    if err := container.Start(process); err != nil { 
     return -1, err 
    } 

    go func(reader io.Reader) { 
     scanner := bufio.NewScanner(reader) 
     for scanner.Scan() { 
      onData(scanner.Bytes()) 
     } 
     if err := scanner.Err(); err != nil { 
      onErr(err) 
     } 
    }(reader) 

    return handler.forward(process) 
} 

Это также работает, но проблема: он ожидает основного процесса, чтобы выйти перед запуском. Иногда он запускается, но моя память переходит в 100% после вызова этой функции в 5-7 раз с помощью простой команды whoami.

Я уверен, что я что-то делаю неправильно, я просто не знаю, что. Или мое понимание контейнеров не позволяет мне?

Я использовал этот проект в качестве ссылки: https://github.com/opencontainers/runc

ответ

2

Это, вероятно, лучше использовать докер в качестве ссылки для вашего дела, потому что он использует то же libcontainer.Container объектов для запуска и ехеса нового процесса в контейнере. Вы можете найти код, взаимодействующий с libcontainer здесь: https://github.com/docker/docker/tree/master/daemon/execdriver/native

Также лучше разместить весь код, чтобы люди могли попробовать и отладить его, чтобы помочь вам.

EDIT: Вот пример кода для запуска нескольких контейнеров: https://gist.github.com/anonymous/407eb530c0cb6c87ec9f

Я запущенной его как

go run procs.go path-to-busybox 

Вы можете увидеть ps, что на самом деле есть несколько процессов в контейнере. Не стесняйтесь спрашивать, есть ли у вас какие-либо вопросы.

+0

Runc использует ту же библиотеку (на самом деле она была взята OpenContainers AFAIK), и было легче следовать, чем докер. Я думал, что код будет слишком длинным, так как он плотно интегрирован в приложение, над которым я работаю. Есть ли конкретные детали, которые мне нужно включить, возможно? – Sthe

+1

Простой пример минимального запуска с двумя процессами. Я могу попытаться написать пример с чистым libcontainer, если хотите. – LK4D4

+0

+1 за предложение: я пытался изолировать код в течение последних 20 минут, но он слишком длинный, потому что это разные пакеты, которые работают вместе, а сам контейнер нуждается в файле конфигурации, который похож на страницу A4. Есть ли что-нибудь, что вы можете заметить из кода, который я предоставил? Они являются единственными кодовыми блоками, взаимодействующими с контейнером. Возможно, подход? – Sthe

Смежные вопросы