0

I'm wishing to run a command from C# to a container set up via docker-compose. In Powershell, I run this command and the file is created:

docker-compose exec database sh -c "mysqldump -u((username)) -p((password)) ((databasename)) > /backups/test.sql"

When I run the following code it seems to ignore the environment variables, even though I have them set. It only creates a file named backup.sql and the SQL outputted to the file indicates that no database was selected. I've verified the env variables are set by outputting the last parameters string to the console.

var exportPath = $"/backups/backup.sql {DateTime.Now}"; 
using (var runspace = RunspaceFactory.CreateRunspace())
{
    runspace.Open();
    runspace.SessionStateProxy.Path.SetLocation(Path.GetFullPath(".."));
    using (var pipeline = runspace.CreatePipeline())
    {

        var cmd = new Command("docker-compose");
        cmd.Parameters.Add("exec");
        cmd.Parameters.Add("database");
        cmd.Parameters.Add($"sh -c \"mysqldump - u{GetEnv("MYSQL_USERNAME")} " +
            $"-p{GetEnv("MYSQL_PASSWORD")} {GetEnv("MYSQL_DATABASE")} > {exportPath} \"");
        pipeline.Commands.Add(cmd);
        pipeline.Invoke();
    }
}

GetEnv is just a convenience method for Environment.GetEnvironmentVariable

I'm fairly certain that I am not setting the parameters right, but I don't know where to go from here.

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
eltiare
  • 1,817
  • 1
  • 20
  • 28

2 Answers2

2

I gave up and used CliWrap because it is easier to debug. I couldn't figure out how to set the current directory, but fortunately I could modify the rest of the program to look for stuff in the current directory.

using CliWrap;
using CliWrap.Buffered;

var now = DateTime.Now.ToString().Replace("/", "-").Replace(" ", "-");
var exportPath = $"/backups/backup.sql-{now}";

var cmd = $"exec -T database sh -c \"mysqldump -u{GetEnv("MYSQL_USER")} " +
          $"-p{GetEnv("MYSQL_PASSWORD")} {GetEnv("MYSQL_DATABASE")} > {exportPath}\"";

Console.WriteLine(cmd);

var result = await Cli.Wrap("docker-compose")
    .WithArguments(cmd)
    .ExecuteBufferedAsync();

Console.WriteLine(result.StandardOutput);
Console.WriteLine(result.StandardError);

The library can be found here: https://github.com/Tyrrrz/CliWrap

Tyrrrz
  • 2,492
  • 1
  • 19
  • 29
eltiare
  • 1,817
  • 1
  • 20
  • 28
2

I came across to FluentDocker which seems like a nice way to run docker-compose from c#.

Here is an example from the project page:

using (
        var container =
          new Builder().UseContainer()
            .UseImage("kiasaki/alpine-postgres")
            .ExposePort(5432)
            .WithEnvironment("POSTGRES_PASSWORD=mysecretpassword")
            .WaitForPort("5432/tcp", 30000 /*30s*/)
            .Build()
            .Start())
      {
        var config = container.GetConfiguration(true);
        Assert.AreEqual(ServiceRunningState.Running, config.State.ToServiceState());
      }

Disclaimer: I am not affiliated with the project in any way nor have attempted to use it yet.

mentat
  • 2,748
  • 1
  • 21
  • 40