Remote development using Docker, WSL 2, Visual Studio Code and X-windows server
This is a work in progress but since the proof of concept is working will post here.
Since I prefer to develop SWI-Prolog using Visual Studio Code, all the development has been done on a single Windows machine. Now all of that can change to doing development with multiple Docker containers including the machine where the SWI-Prolog code is hosted and run. The only things remaining on the Windows side is Visual Studio Code and an X11 server. While this will run the Docker containers using WSL on the Windows machine, it is just a simple exercise to move the Docker containers to other host and and all should still work. Also since the machines are Docker containers, they can easily be created with a Dockerfile, and since a Dockerfile is small in comparison to the footprint of a virtual machine and all in text, the Dockerfiles can easily be put in revision control such as Git and even made public on GitHub. So this means that now you can not only share the code but the entire tool chain and environment with a few added text files; however as noted somethings in this scenario are constants: Docker, Visual Studio Code, and for SWI-Prolog GUI tools the need for X-windows server.
What follows is essentially Remote development in WSL modified to demonstrated the same with SWI-Prolog.
Install a Windows X-windows server (I use VcXsrv)
Start X11 server.
For VcXsrv configuration:
Multiple windows
Display number: -1
Start no client
Clipboard
Primary Selection
Native opengl
Disable access control (TODO: This should not be used, use firewall rules etc.)
Follow the steps in Remote development in WSL until you get to Python development.
Add Ubuntu to Windows Terminal
Using Windows Terminal open settings
Th will need a new GUID.
Using Windows PowerShell
[guid]::NewGuid()
which will generate GUID
Guid
----
d23fb715-097c-4f16-89dd-98569e048fba
Do not use the one where demonstrated above as a GUID need to be a Globally Unique ID, (GUID).
For "list":
add something like (Don’t ask me to much on this I barely understand the details)
{
"guid": "{9e7de027-0fca-5811-94e7-9e6d96b5b97f}",
"hidden": false,
// Ubuntu 20.04
// Based on Docker image
"name": "SWI-Prolog",
"source": "Windows.Terminal.Wsl",
// start SWI-Prolog
// "commandline": "wsl.exe -u eric -d Ubuntu_SWI-Prolog swipl",
// defaults to starting bash
"commandline": "wsl.exe -u <user> -d Ubuntu_SWI-Prolog",
"startingDirectory" : "//wsl$/Ubuntu_SWI-Prolog/home/<user>",
"icon": "C:\\Program Files\\swipl\\swipl.ico"
}
where you will need to change <user> to your user name.
Note: I duplicated then modified the WSL Ubuntu distro using the WSL import and export so that I could have a distro specifically for SWI-Prolog. (TODO: Create a Dockerfile for the distro.)
Install Visual Studio Code extension: Remote - WSL
Using Windows Terminal start WSL distro by clicking and then selecting SWI-Prolog from drop down list.
Using WSL SWI-Prolog distro
Verify SWI-Prolog is installed and working
eric@WINDOWS-6F874NS:~$ swipl --version
SWI-Prolog version 8.3.10 for x86_64-linux
Verify current directory
eric@WINDOWS-6F874NS:~$ pwd
/home/eric
Make directory for development
eric@WINDOWS-6F874NS:~$ mkdir -p projects/SWI-Prolog/helloWord && cd projects/SWI-Prolog/helloWord
eric@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord$
Make simple Hello World
style predicate for demonstration purposes
eric@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord$ echo ":- write('Hello from SWI-Prolog on Ubuntu on Windows\u0021\n')." > hello.pl
Demonstrate predicate
eric@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord$ swipl --quiet -g halt hello.pl
Hello from SWI-Prolog on Ubuntu on Windows!
Startup Visual Studio Code set to this directory
eric@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord$ code .
/mnt/c/Program Files/Microsoft VS Code/bin/code: 46: cannot create /tmp/remote-wsl-loc.txt: Permission denied
Installing VS Code Server for x64 (d2e414d9e4239a252d1ab117bd7067f125afd80a)
Downloading: 100%
Unpacking: 100%
Unpacked 2357 files and folders to /home/eric/.vscode-server/bin/d2e414d9e4239a252d1ab117bd7067f125afd80a.
eric@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord$
In Visual Studio Code
Install extension: VSC-Prolog
Using VS Code change to the extensions panel by clicking in the left panel.
In the extensions search input enter prolog
For VSC-Prolog
click
Switch the left panel back to the files view by clicking
Create file: path.pl
% From: https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_15.html
edge(1,2).
edge(1,4).
edge(1,3).
edge(2,3).
edge(2,5).
edge(3,4).
edge(3,5).
edge(4,5).
connected(X,Y) :- edge(X,Y).
connected(X,Y) :- edge(Y,X).
path(A,B,Path) :-
travel(A,B,[A],Q),
reverse(Q,Path).
travel(A,B,P,[B|P]) :-
connected(A,B).
travel(A,B,Visited,Path) :-
connected(A,C),
C \== B,
\+member(C,Visited),
travel(C,B,[C|Visited],Path).
Since there is invalid configuration for VSC-Prolog that is not allowing the linter to work, a output panel will open with the message:
`Cannot lint the prolog file. The Proog executable was not found. Use the ‘prolog.executablePath’ setting to configure
To fix this
From the menu select File
> Preferences
> Settings
For Search settings
enter prolog
Select Remote [...]
For Prolog: Executable Path
remove /usr/bin/siwpl
so that value is empty.
Close the settings
panel
Open terminal (Ctrl+`)
Start SWI-Prolog
root@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord# swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.10)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
Consult file: path.pl
?- [path].
true.
List the predicate path
?- listing(path).
path(A, B, Path) :-
travel(A, B, [A], Q),
reverse(Q, Path).
Run the predicate path
?- path(1,5,P).
P = [1, 2, 5] ;
P = [1, 2, 3, 5] ;
P = [1, 2, 3, 4, 5]
...
Trace the predicate path
?- trace,path(1,5,P).
Call: (11) path(1, 5, _30240) ? creep
Call: (12) travel(1, 5, [1], _30780) ? creep
Call: (13) connected(1, 5) ? creep
Call: (14) edge(1, 5) ? creep
Fail: (14) edge(1, 5) ? creep
Redo: (13) connected(1, 5) ? creep
Call: (14) edge(5, 1) ? creep
Fail: (14) edge(5, 1) ? creep
Fail: (13) connected(1, 5) ? creep
Redo: (12) travel(1, 5, [1], _30780) ? creep
Call: (13) connected(1, _31202) ? creep
Call: (14) edge(1, _31202) ? creep
Exit: (14) edge(1, 2) ? creep
Exit: (13) connected(1, 2) ? creep
Call: (13) 2\==5 ? creep
Exit: (13) 2\==5 ? creep
Call: (13) lists:member(2, [1]) ? creep
Fail: (13) lists:member(2, [1]) ? creep
Redo: (12) travel(1, 5, [1], _30780) ? creep
Call: (13) travel(2, 5, [2, 1], _30780) ? creep
Call: (14) connected(2, 5) ? creep
Call: (15) edge(2, 5) ? creep
Exit: (15) edge(2, 5) ? creep
Exit: (14) connected(2, 5) ? creep
Exit: (13) travel(2, 5, [2, 1], [5, 2, 1]) ? creep
Exit: (12) travel(1, 5, [1], [5, 2, 1]) ? creep
Call: (12) lists:reverse([5, 2, 1], _30240) ? creep
Exit: (12) lists:reverse([5, 2, 1], [1, 2, 5]) ? creep
Exit: (11) path(1, 5, [1, 2, 5]) ? creep
P = [1, 2, 5] ;
Redo: (14) connected(2, 5) ?
...
To use gtrace which uses X-windows a few system variables need to be configured.
Reference: How to set up working X11 forwarding on WSL2
Edit .bashrc
Check for existing export DISPLAY
and export LIBGL_ALWAYS_INDIRECT
, there should be none. If there are some and they are not like the following edit, I have not idea on how to make the change.
At the end of the file add
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1
In the terminal with swipl
running
halt swipl
Switch user to <user>
root@WINDOWS-6F874NS:/home/eric# su eric
eric@WINDOWS-6F874NS:~$
Apply the changes to .bashrc
eric@WINDOWS-6F874NS:~$ . ~/.bashrc
Start swipl
again
eric@WINDOWS-6F874NS:~/projects/SWI-Prolog/helloWord$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.10)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?-
Using SWI-Prolog verify predicate works
[path].
true.
?- path(1,5,P).
P = [1, 2, 5] ;
P = [1, 2, 3, 5] ;
P = [1, 2, 3, 4, 5]
...
Using SWI-Prolog use gtrace/0 with predicate which should automatically start up X-window with SWI-Prolog gtrace running in it.
?- gtrace,path(1,5,P).
% The graphical front-end will be used for subsequent tracing
P = [1, 2, 5] ;
...
Errors (Included here so that they can be indexed by search engines such as Google)
?- gtrace,path(1,5,P).
% The graphical front-end will be used for subsequent tracing
[PCE fatal: @display/display: Failed to connect to X-server at `': no DISPLAY environment variable
*********************************************************************
* You MUST be running the X11 Windowing environment. If you are, *
* check the setting of your DISPLAY environment variable as well *
* the access rights to your X11 server. See xauth(1) and xhost(1). *
*********************************************************************
in: <No exception goal>
]
Host stack:
[15] pce_principal:send(@emacs_mark_list/emacs_bookmark_editor, append(new(_12646, dialog)))
[14] Send-method on @emacs_mark_list/emacs_bookmark_editor: emacs_bookmark_editor->initialise
[13] '$c_call_prolog'
[12] pce_principal:new(@emacs_mark_list/emacs_bookmark_editor, emacs_bookmark_editor)
[11] Send-method on @emacs/emacs: emacs->initialise(@emacs_buffers/dict)
% The following threads wouldn't die: [main]
Personal Notes
References:
Official Images on Docker Hub
Overview of Docker Compose
Develop with Docker
Guidelines for Linux package managers - Why are executables named what they are, e.g. swipl, what are the types of packages that should be created, e.g. swi-prolog-nox
Containers on Windows documentation
Open Container Initiative - Think Docker or VXD, this is open source.
Deploy a registry server - Think private DockerHub on PC
What you need to know about upcoming Docker Hub rate limiting
Checking Your Current Docker Pull Rate Limits and Status
The great Docker split
Docker Newsletter
Introduction to Containers
systemctl failed to connect to bus - docker
A Practical Introduction to Container Terminology
SO Docker tag info
GoogleContainerTools
GoogleContainerTools/container-diff
Docker Engine API (Using JSON data format)
How do I connect to the remote Docker Engine API? (Running on Windows OS)
Using Docker Engine API securely
Working with Docker APIs
PSA: Beware of Exposing Ports in Docker
How do you mount the docker socket on Windows?
Docker Tips : about /var/run/docker.sock
https://www.linuxserver.io/ - We are a group of like minded enthusiasts from across the world who build and maintain the largest collection of Docker images on the web.
linuxserver/code-server - Code-server is VS Code running on a remote server, accessible through the browser.
UNIX Domain Sockets
UNIX domain sockets
Unix domain sockets vs. internet sockets
Play with Docker Classroom
Capture the X11 protocol’s traffic
Gist using /var/run/docker.sock with socat and nc.
Docker Internals - a blog.
Docker Registry
GitHub Docker Registry
Implementing a Self-Hosted Docker Registry on Raspberry Pi
ubuntu running under WSL2 not seeing Docker daemon at unix:///var/run/docker.sock - Use docker context ls
then docker ps
Installing various versions of PowerShell
Install .NET on Linux
Daemon socket option - The Docker daemon can listen for Docker Engine API requests via three different types of Socket: unix, tcp, and fd.
Update DISPLAY env for already running docker containers for X11 forwarding over SSH
Manage sensitive data with Docker secrets
Best Docker Support Resources for Troubleshooting
Kubernetes is dropping Docker support?!
Don’t Panic: Kubernetes and Docker
Dockershim Deprecation FAQ
Kubernetes Documentation
Introducing Container Runtime Interface (CRI) in Kubernetes
Start coding in seconds on GitHub with Codespaces
Running both Windows and Linux containers at the same time
Running Docker Windows and Linux Containers Simultaneously - As the blog is 2 years old this might have significantly changed, but this is the best article I have seen so far.
Win10+Docker: Hybrid swarm on the Desktop - This one has more details but you need to link to other blogs to get even more of the detail. Have not tried this example yet.
Docker Desktop for Windows user manual - resources
Configurations
- Linux containers in WSL 2 mode
- Linux containers in Hyper-V mode
- Windows containers.
Windows base OS images - These are Docker images that use the Windows OS and not a Linux OS. These only run on a host with a Windows OS installed as you need a Windows OS license and the Docker images use the license of the host OS.
Windows container version compatibility
Windows 10 release information
Software to compare Windows system snapshots
8 Tools to Track Registry and File Changes by Comparing Before and After Snapshots
docker diff - Only does files names not contents of files such as log files or the registry.
SO Q&A Docker difference between two containers - Comment notes: export both containers, untar them and run a diff
Also, for single-container scenarios, using Docker Compose provides tool-independent configuration in a way that a single Dockerfile does not. Configuration settings such as volume mounts for the container, port mappings, and environment variables can be declared in the docker-compose YML files.
Uses:
For teachers needing to help their students create their first tool-chain for a development environment. Also with Visual Studio Code in the mix and some associated extensions, the students can collaborate with each other or the teacher with the student(s), e.g. Introducing Visual Studio Live Share, Live Share Extension Pack, Development Containers in Education: A Guide for Instructors
A current question is if a teacher wants to review and comment on the current code of a student, then where should the code be stored and how? Since each student could have a separate directory on a common server then how does the teacher bring up each students work and then quickly switch to the next students work without leaving the development environment?
See:
Working with Containers
Adding another local file mount
The Remote - Containers extension supports two primary operating models:
- You can use a container as your full-time development environment.
- You can attach to a running container to inspect it.
VS Code Working with containers
VS Code Remote Development
microsoft/vscode-remote-try-java
Developing inside a Container
Remote development in Containers
VS Code extension: Remote - SSH
VS Code extension: Remote - WSL
LXD is not the same as Docker, but you can try LXD online
LXD vs Docker
List of Linux containers
OS-level virtualization
Microservices