How to manage docker from C# with SSH

Hello everybody,

today I want to write a few words about how to work with Docker with help of C#.

Recently I've got a challenge to find the way how to manage Docker. Initially I've tried Docker.Dotnet library. It has quite interesting options for management of docker, but from my own prospective it's not very convenient for management.  After some trial/error efforts I've decided to try another option. I tried using SSH connection in order to manage linux instance with Docker. In order to have access to CentOs I've used SSH.Net.

In order to have option for mocking of SSH I've created following interface:

    public interface ISshManager
    {
        string IpHost { get; set; }
        string UserName { get; set; }
        string Password { get; set; }
        string ExecuteCommand(string command, string ipHost = null, string username = null, string password = null);
        void UploadFile(string sourceFile, string destination, string ipHost = null, string username = null, string password = null);
        void ExecuteBashFile(string bashSourceFile, string ipHost = null, string username = null, string password = null);
        void ExecuteBash(string bash, string ipHost = null, string username = null, string password = null);
    }

Also I've added following implementation of this interface:

    public class SshManager : ISshManager
    {
        public string IpHost { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        private int _Port = 22;
        public string ExecuteCommand(string command, string ipHost = null, string username = null, string password = null)
        {
            Init(ref ipHost, ref username, ref password);

            string result = string.Empty;

            using (var client = new SshClient(ipHost, username, password))
            {
                client.Connect();
                result = client.RunCommand(command).Result;
                client.Disconnect();
            }
            return result;
        }

        private void Init(ref string ipHost, ref string username, ref string password)
        {
            ipHost = ipHost ?? IpHost;
            username = username ?? UserName;
            password = password ?? Password;
        }


        public void ExecuteBash(string bash, string ipHost = null, string username = null, string password = null)
        {
            Init(ref ipHost, ref username, ref password);
            string result = string.Empty;

            try
            {
                using (var client = new SshClient(ipHost, username, password))
                {
                    client.Connect();
                    string command = bash;
                    Stream stdout = Console.OpenStandardOutput();

                    var input = new MemoryStream(Encoding.ASCII.GetBytes(command));
                    var shell = client.CreateShell(input, stdout, stdout);
                    shell.Stopped += delegate (object sender, EventArgs e)
                    {
                        Console.WriteLine("\nDisconnected...");
                    };
                    shell.Start();
                    Thread.Sleep(1000);
                    shell.Stop();
                    client.Disconnect();
                }
            }
            catch (Exception ex)
            {
                // Exception stuff
            }
        }

        public void ExecuteBashFile(string bashSourceFile, string ipHost = null, string username = null, string password = null)
        {
            string bash = File.ReadAllText(bashSourceFile);
            ExecuteBash(bash, ipHost, username, password);
        }

        public void UploadFile(string sourceFile, string destination, string ipHost = null, string username = null, string password = null)
        {
            Init(ref ipHost, ref username, ref password);
            using (var client = new SftpClient(ipHost, _Port, username, password))
            {
                client.Connect();
                if (client.IsConnected)
                {
                    string workingDirectory = destination;
                    string destinationName = workingDirectory + Path.GetFileName(sourceFile);
                    client.ChangeDirectory(workingDirectory);
                    using (var fileStream = new FileStream(sourceFile, FileMode.Open))
                    {
                        client.BufferSize = 4 * 1024; // bypass Payload error large files
                        client.UploadFile(fileStream, destinationName, null);
                    }
                }
            }
        }
    }

Some examples of usage of this class:

Creation ( you can use DI for making it more beautifull )

ISshManager sshManager = new SshManager()
                {
                    IpHost = ipHost,
                    UserName = userName,
                    Password = password
                };

Then you can create folder:

sshManager.ExecuteCommand("mkdir -p folderName"); //create folder folderName

If you need to execute two commands, you can use && for such purpose like this:

sshManager.ExecuteCommand($"cd {folderName} &&rm docker-compose.yml -f\n ls");

Those line will go to folder folder name, and then will remove file docker-compose.yml

Also you can upload file like this:

sshManager.UploadFile("Files/RabbitMQ/docker-compose.yml", $"/{folderName}");

No Comments

Add a Comment