Dockerizing Linux server (continue)
- 1. Install and configure docker
- 2. Docker config files.
- 3. Main command to manipulate docker containers and images
- 4. Docker disk structure
- 5. Connect to Docker API
- 6. Setup Basic AU to control docker.
- 7. Protect docker password with SSL
- 8. Client software to manage docker based on Docker.DotNet.
1. Install and configure docker
This notes continues page Dockerizing Linux server.
My first task in this server will be add new disk space and move root docker directory to new disk. So:
# lsblk # sudo fdisk -l # sudo mkdir /docker # sudo nano /etc/fstab
Than install docker, check it,
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" # sudo apt-get update # apt-cache policy docker-ce # sudo apt-get install -y docker-ce # sudo systemctl status docker # sudo docker info # sudo curl --unix-socket /var/run/docker.sock http://localhost/v1.41/containers/json
and move to the new directory.
# sudo service docker stop # df # sudo nano /etc/docker/daemon.json # sudo cat /etc/docker/daemon.json # sudo rsync -aP /var/lib/docker/ /docker # sudo mv /var/lib/docker /var/lib/docker.old # sudo service docker start # sudo rm -rf /var/lib/docker.old
This is a benefits of use separate volume to docker.
Best practice is also immediately create login for docker client, this allow authenticated request from docker client to docker server.
After that best practice is to check docker network - availability of host.
# sudo docker run --rm -it busybox
2. Docker config files.
Docker has a couple of config - dockerService config, docker daemon config,
# sudo cat /etc/docker/daemon.json # sudo cat /lib/systemd/system/docker.service # sudo systemctl status docker # journalctl -u docker # sudo docker info # sudo docker network ls --no-trunc
and docker client config (contains AU data after docker login).
# docker login # sudo cat .docker/config.json
3. Main command to manipulate docker containers and images
Main command to manipulate docker containers and images (more Dockerizing Linux server):
list containers # sudo docker ps list all containers # sudo docker ps -a list images # sudo docker images # sudo docker images --no-trunc start container as disconnected daemon # sudo docker run -d -p 5000:5000 --restart always --name 5shitmoney 5-shit-money:latest check opened ports # sudo netstat -tunlp perform one command # sudo docker exec -it 7dde487b4424 ls -la /var/lib/registry interactively going inside container # sudo docker exec -it 7dde487b4424 bash compose container from YML config file and start as daemon # sudo docker-compose -f registry-compose.yml up -d # commit changes # sudo docker container commit 7bfb7cc3d51c coinbase:latest backup docker (but without volumes in /var !!) # sudo docker save 5-shit-money:latest | gzip > 5-shit-money.tar.gz # pull container from docker.io (or other registry defined in config( sudo docker pull alexev275/coinbase rename image #sudo docker tag 7bfb7cc3d51c localhosh:5000/coinbase delete all related images (force mode) # sudo docker images -a | grep "localhosh" | awk '{print $3}' | xargs sudo docker rmi -f rebuild container # sudo docker build -f digiwage1.dockerfile -t alexev275/digiwage . list containers # sudo docker container ls -a # sudo docker container ls -a --no-trunc stop container # sudo docker container stop 7bfb7cc3d51c # inspect image sudo docker image inspect alexev275/digiwage list all volumes # sudo docker volume ls get container logs # sudo docker logs 7bfb7cc3d51c stop docker service docker service scale [servicename]=0
4. Docker disk structure
Docker has cool and understandable dick structure.
This is example of container configuration Container-config.json.
Most usable is /volume structure. If you include to dockerfile magic string
VOLUME /root/share
this string allow you to receive shared folder to transfer data with docker host. For example, I have a issue to install ping util inside docker, therefore I simple copy needed files to volume and I receive it inside docker.
5. Connect to Docker API
Docker can connect with remote socket, but firstly need to change docker daemon start command.
Then after reload and restart daemon we can check workable unix socket.
# sudo nano /lib/systemd/system/docker.service # sudo cat /lib/systemd/system/docker.service # sudo systemctl daemon-reload # sudo service docker restart # sudo curl --unix-socket /var/run/docker.sock http://localhost/v1.41/containers/json
6. Setup Basic AU to control docker.
This is simplest way without SSL. So, firstly need to create password file.
# sudo apt-get install nginx # sudo apt-get install apache2-utils # sudo htpasswd -c /etc/nginx/.htpasswd docker # cat /etc/nginx/.htpasswd
NGINX after installation working with account www_data, this account don't allow access to docker, therefore first step is change NGINX account to ROOT.
# sudo nano /etc/nginx/nginx.conf
Nginx automatically activate sites from directory sites-enabled/sites-available, so no need to additionally changing something in main config, we can create additionally config.
# sudo tee /etc/nginx/sites-enabled/docker <<EOF # upstream docker { # server unix:/var/run/docker.sock; # } # server { # listen 4444 default_server; # location / { # proxy_pass http://docker; # auth_basic_user_file /etc/nginx/.htpasswd; # auth_basic "Access restricted"; # } # } # EOF # sudo service nginx restart
Than, if we made always without mistake, we rich finally goal - Basic AU for docker control.
# curl -i http://docker:XXXXXXXXXXXXXXX@127.0.0.1:4444/info
Of course, more secure way is use SSL to protect transfer password in clear form. You can use even self-signed certificate for this purpose - Protect Docker Registry by Nginx. Of course, for use self-signed certificate in client software we need to avoid certificate chain - HttpClient with JSON communication to server with avoid check SSL-certificates chain .
7. Protect docker password with SSL.
Usually first step is check certificate. As you can see in the screen below one certificate is correct, however another one is wrong.
If certificate is correct we can use it to protect password for docker management.
8. Client software to manage docker based on Docker.DotNet.
Unfortunately directly use https://github.com/dotnet/Docker.DotNet to manage docker software with basic AU is impossible because packages don't prepared correctly.
Therefore I have create second package from source code. Workable result I have uploaded to https://github.com/Alex-1347/DockerDotNetWrapper.
This is my code.
1: Imports Docker.DotNet.Models
2: Partial Module Program
3: Public Class DockerReport
4: Public Property SystemInfo As SystemInfoResponse
5: Public Property Volumes As VolumesListResponse
6: Public Property Images As IList(Of ImagesListResponse)
7: Public Property Containers As IList(Of ContainerListResponse)
8: Public Property Networks As IList(Of NetworkResponse)
9: End Class
10: End Module
1: Imports System
2: Imports Docker.DotNet
3: Imports Docker.DotNet.BasicAuth
4: Imports Docker.DotNet.Models
5: Imports Newtonsoft.Json
6: Imports Newtonsoft.Json.Linq
7:
8: 'https://github.com/dotnet/Docker.DotNet
9:
10: Partial Module Program
11:
12: Sub Main(args As String())
13: 'Console.WriteLine("Pass to be encrypted >")
14: 'Dim pass1 = Console.ReadLine
15: 'Console.WriteLine("Encrypted string >")
16: 'Dim pass2 = Console.ReadLine
17: 'Console.WriteLine(EncryptString(pass1, pass2))
18: 'End
19: Dim DockerReport1 As New DockerReport
20: Console.Write("Get Password" & vbCrLf & ">")
21: Dim PassStr = ReadPassword()
22: Console.WriteLine()
23: Dim Credential = New BasicAuthCredentials(My.Resources.Login, DecryptString(My.Resources.Pass, PassStr))
24: Dim DockerHub = New DockerClientConfiguration(New Uri(My.Resources.Url), Credential).CreateClient()
25: Console.WriteLine($"Docker {My.Resources.Url} connected.")
26:
27: DockerReport1.SystemInfo = DockerHub.System.GetSystemInfoAsync().Result
28: Dim JSystemInfo As JObject = JToken.FromObject(DockerReport1.SystemInfo)
29: Console.WriteLine($"{ DockerReport1.SystemInfo.Name} { DockerReport1.SystemInfo.DockerRootDir} ")
30: Console.WriteLine()
31:
32: DockerReport1.Volumes = DockerHub.Volumes.ListAsync.Result
33: Console.WriteLine($"Found {DockerReport1.Volumes.Volumes.Count} volumes")
34: DockerReport1.Volumes.Volumes.ToList.ForEach(Sub(X) Console.WriteLine($"{X.Name}"))
35: Console.WriteLine()
36:
37: DockerReport1.Images = DockerHub.Images.ListImagesAsync(New ImagesListParameters With {.All = True}).Result
38: Console.WriteLine($"Found {DockerReport1.Images.Count} images")
39: DockerReport1.Images.ToList.ForEach(Sub(X)
40: X.RepoTags.ToList.ForEach(Sub(Y) Console.WriteLine(Y.ToString))
41: End Sub)
42: Console.WriteLine()
43:
44: DockerReport1.Networks = DockerHub.Networks.ListNetworksAsync().Result
45: Console.WriteLine($"Found {DockerReport1.Networks.Count} networks")
46: DockerReport1.Networks.ToList.ForEach(Sub(X) Console.WriteLine($"{X.ID} : {X.Name}"))
47: Console.WriteLine()
48:
49: DockerReport1.Containers = DockerHub.Containers.ListContainersAsync(New ContainersListParameters With {.Limit = 10}).Result
50: Console.WriteLine($"Found {DockerReport1.Containers.Count} containers")
51: DockerReport1.Containers.ToList.ForEach(Sub(X) Console.WriteLine(X.ID))
52: Console.WriteLine()
53:
54: Dim Plugins As IList(Of Plugin) = DockerHub.Plugin.ListPluginsAsync(New PluginListParameters).Result
55: Console.WriteLine($"Found {Plugins.Count} plugins")
56: Plugins.ToList.ForEach(Sub(X) Console.WriteLine(X.Name))
57: Console.WriteLine()
58: Try
59: Dim Secrets As IList(Of Secret) = DockerHub.Secrets.ListAsync().Result
60: Console.WriteLine($"Found {Secrets.Count} secrets")
61: Secrets.ToList.ForEach(Sub(X) Console.WriteLine(X.ID))
62: Catch ex As Exception
63: Console.WriteLine("DockerHub.Secrets: " & ex.Message)
64: End Try
65:
66: Try
67: Dim Swarms As IEnumerable(Of SwarmService) = DockerHub.Swarm.ListServicesAsync().Result
68: Console.WriteLine($"Found {Swarms.Count} swarms")
69: Swarms.ToList.ForEach(Sub(X) Console.WriteLine(X.ID))
70: Console.WriteLine()
71: Catch ex As Exception
72: Console.WriteLine("DockerHub.Swarm: " & ex.Message)
73: End Try
74:
75: Try
76: Dim Tasks As IList(Of TaskResponse) = DockerHub.Tasks.ListAsync().Result
77: Console.WriteLine($"Found {Tasks.Count} tasks")
78: Tasks.ToList.ForEach(Sub(X) Console.WriteLine(X.ID))
79: Console.WriteLine()
80: Catch ex As Exception
81: Console.WriteLine("DockerHub.Tasks: " & ex.Message)
82: End Try
83:
84: Dim JReport As JObject = JToken.FromObject(DockerReport1)
85: Dim DockerReportString As String = JsonConvert.SerializeObject(JReport, New JsonSerializerSettings With {.Formatting = Formatting.Indented})
86: Dim DockerReportFileName As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DockerReport.json")
87: IO.File.WriteAllText(DockerReportFileName, DockerReportString)
88: Process.Start("C:\Program Files\Mozilla Firefox\firefox.exe", DockerReportFileName)
89: End Sub
....
115: End Module
And this is a result of my test DockerReport.json.
|