Home > Enterprise >  How to run `docker exec -it <container_name> bash -c "some commands"` using golang s
How to run `docker exec -it <container_name> bash -c "some commands"` using golang s

Time:12-21

I'm using docker's sdk in golang to execute a docker exec command.

func (dn *dockerNode) execCommand(ctx context.Context, cmd []string) (*execResult, error) {
    execId, err := dn.cl.ContainerExecCreate(ctx, dn.contId, types.ExecConfig{
        AttachStderr: true,
        AttachStdout: true,
        Tty:          true,
        Cmd:          cmd,
    })

    if err != nil {
        return nil, fmt.Errorf(
            "cannot create command \"%s\":\n %v",
            strings.Join(cmd, " "),
            err,
        )
    }

    res, err := dn.InspectExecResp(ctx, execId.ID)
    if err != nil {
        return nil, fmt.Errorf(
            "cannot execute command \"%s\":\n %v",
            strings.Join(cmd[:], " "),
            err,
        )
    }

    if res.exitCode != 0 {
        return &res, fmt.Errorf(
            "command \"%s\" exit with code %d:\n % v",
            strings.Join(cmd[:], " "),
            res.exitCode,
            res)
    }

    return &res, nil
}

This dn.execCommand works fine just for some vanilla docker exec foo bar format command, but now I'd like to use it to run something equivalent to docker exec bash -c "cd mydir && ./my_shell.sh". This is because the cd command only works with docker exec bash -c. I tried passing this with

    res, err = dn.execCommand(
        ctx,
        []string{
            "bash",
            "-c",
            "\"cd mydir && ./my_shell.sh\"",
        },
    )

But it gave me command "bash -c "cd mydir && ./my_shell.sh" " exit with code 127

I wonder how to modify the original function to make it support the docker exec bash -c use case.

CodePudding user response:

Your last command has an extra layer of quotes.

command := []string{
        "bash",
        "-c",
        "cd mydir && ./my_shell.sh",
//      ^^no quotes inside string^^
}

If you were to run a similar command on the host

bash -c "cd mydir && ./my_shell.sh"

the shell would take the double-quoted string and turn it into a single word, and then discard the quotes. You can see this in part by putting the word echo in front of the command line, so the processed command gets printed out rather than executed; the double-quotes will be gone. What you're running is more similar to

bash -c '"cd mydir && ./my_shell.sh"'

Also note that the "github.com/docker/docker/api/types".ExecConfig structure contains a WorkingDir field, so you might be able to avoid this wrapper. Scripting docker exec also frequently isn't the best design, since you need unlimited administrator-level permissions over the host to use it, and since a container typically only runs one process.

  • Related