How to Install Apache Guacamole as Docker Container on Ubuntu

Apache Guacamole is free, open source clientless remote desktop application that allows you to access remote Desktop and Server machines via a web browser. It supports standard protocols like VNC, RDP, and SSH, and use HTML5 for remote connection. It can run on most Linux distributions, and the client runs on any modern web browser. You don't need to install any software on your system. Just browse and connect to any remote server defined on your server.

In this post, we will show you how to install the Apache Guacamole server and client with Docker on Ubuntu 22.04.

Prerequisites

  • A server running Ubuntu 22.04.
  • A root password is configured on the server.

Install Docker Engine

It is always recommended to install the latest version of Docker to your server.

First, install the required dependencies using the following command:

apt install ca-certificates curl gnupg lsb-release -y

After installing all the dependencies, add the Docker GPG key and repository with the following command:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor > /etc/apt/trusted.gpg.d/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list

Next, update the repository and install the Docker Engine package with the following command:

apt update -y
apt install docker-ce docker-ce-cli containerd.io -y

Once the installation is completed, verify the Docker version using the following command:

docker --version

You should get the following output:

Docker version 20.10.18, build b40c2f6

Install Docker Compose

You will also need to install the Docker Compose on your server. You can install it with the following command:

curl -sL "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Next, verify the Docker Compose version using the following command:

docker-compose --version

You will get the following output:

docker-compose version 1.29.2, build 5becea4c

Download Apache Guacamole Server and Client

First, you will need to download the Apache Guacamole Server and Client image from the Docker registry.

First, download the server image with the following command:

docker pull guacamole/guacd

You should see the following output:

Using default tag: latest
latest: Pulling from guacamole/guacd
4b7b4a8876e2: Pull complete 
4e542e9cf89d: Pull complete 
9741340fbbb2: Pull complete 
96fa725029d6: Pull complete 
0f0a6df13f2a: Pull complete 
a4fa6e99a790: Pull complete 
07365dfaa371: Pull complete 
Digest: sha256:efdc09beba21e2c5d7c8c77e8c6b95ffd173d75645c9c41b6024f5b835d2a034
Status: Downloaded newer image for guacamole/guacd:latest
docker.io/guacamole/guacd:latest

First, download the client image with the following command:

docker pull guacamole/guacamole

You should see the following output:

Using default tag: latest
latest: Pulling from guacamole/guacamole
2b55860d4c66: Pull complete 
2ca45fc4c4ca: Pull complete 
0cd32add6672: Pull complete 
ac52cbbb8ca2: Pull complete 
7f7dc3a9f4cc: Pull complete 
5d7996a24402: Pull complete 
4819d3e4118d: Pull complete 
055afbac1f72: Pull complete 
23ee772344b7: Pull complete 
e44569de6126: Pull complete 
f7d7e8014b18: Pull complete 
Digest: sha256:8a8db8cf9f5359aa20547382213a42a720ea1c5fe86460ded727061e1995d9f2
Status: Downloaded newer image for guacamole/guacamole:latest
docker.io/guacamole/guacamole:latest

Next, verify the downloaded images with the following command:

docker images

You will get the following output:

REPOSITORY            TAG       IMAGE ID       CREATED        SIZE
guacamole/guacd       latest    4086ac9e35a7   9 hours ago    271MB
guacamole/guacamole   latest    959856a45436   10 hours ago   432MB

Launch Apache Guacamole MySQL Container

First, you will need at least one database container for Apache Guacamole authentication. You can download and launch the MySQL container with the following command:

docker run --name guacamoledb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=guacdb -d mysql/mysql-server

You will get the following output:

latest: Pulling from mysql/mysql-server
cdd8b07c6082: Pull complete 
c2f1720beca1: Pull complete 
39f143a8d6de: Pull complete 
118a8285b641: Pull complete 
b45cbcaf75c7: Pull complete 
d4574372e600: Pull complete 
1f565a3cbc52: Pull complete 
Digest: sha256:e30a0320f2e3c7b7ee18ab903986ada6eb1ce8e5ef29941b36ec331fae5f10b2
Status: Downloaded newer image for mysql/mysql-server:latest
c7a9309eac20a7d0bb6f0a16460bf2b678aae741c201efae8974ea64a3736595

Next, create a directory to store the database:

mkdir -p /opt/guacamole/mysql

Next, generate the MySQL initialization script using the following command:

docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > /opt/guacamole/mysql/01-initdb.sql

Next, copy the Guacamole MySQL database initialization script to the MySQL Docker container:

docker cp /opt/guacamole/mysql/01-initdb.sql guacamoledb:/docker-entrypoint-initdb.d

Next, connect to the MySQL database container with the following command:

docker exec -it guacamoledb bash

Once you are connected, you will get the following shell:

bash-4.4# 

Next, list the MySQL initialization script with the following command:

cd /docker-entrypoint-initdb.d/
ls

Output:

01-initdb.sql

Next, connect to the MySQL shell using the following command:

mysql -u root -p

Next, switch the database to guacd and initialize the Guacamole database:

use guacdb;
source 01-initdb.sql;

Next, verify all tables with the following command:

show tables;

You will get the following output:

+---------------------------------------+
| Tables_in_guacdb                      |
+---------------------------------------+
| guacamole_connection                  |
| guacamole_connection_attribute        |
| guacamole_connection_group            |
| guacamole_connection_group_attribute  |
| guacamole_connection_group_permission |
| guacamole_connection_history          |
| guacamole_connection_parameter        |
| guacamole_connection_permission       |
| guacamole_entity                      |
| guacamole_sharing_profile             |
| guacamole_sharing_profile_attribute   |
| guacamole_sharing_profile_parameter   |
| guacamole_sharing_profile_permission  |
| guacamole_system_permission           |
| guacamole_user                        |
| guacamole_user_attribute              |
| guacamole_user_group                  |
| guacamole_user_group_attribute        |
| guacamole_user_group_member           |
| guacamole_user_group_permission       |
| guacamole_user_history                |
| guacamole_user_password_history       |
| guacamole_user_permission             |
+---------------------------------------+

Next, create an admin user and set a password with the following command:

create user [email protected]'%' identified by 'password';
grant SELECT,UPDATE,INSERT,DELETE on guacdb.* to [email protected]'%';

Next, flush the privileges and exit from the MySQL shell with the following command:

flush privileges;
exit;

Next, exit from the MySQL container using the following command:

exit

You can now verify the running container using the following command:

docker ps

You should see the MySQL container in the following output:

CONTAINER ID   IMAGE                COMMAND                  CREATED         STATUS                   PORTS                       NAMES
c7a9309eac20   mysql/mysql-server   "/entrypoint.sh mysq…"   2 minutes ago   Up 2 minutes (healthy)   3306/tcp, 33060-33061/tcp   guacamoledb

You can also check the container logs with the following command:

docker logs guacamoledb

You will get the following output:

[Entrypoint] Starting MySQL 8.0.30-1.2.9-server
2022-10-02T11:31:52.589985Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2022-10-02T11:31:52.592352Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.30) starting as process 1
2022-10-02T11:31:52.602604Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-10-02T11:31:52.875859Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-10-02T11:31:53.131572Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-10-02T11:31:53.131639Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2022-10-02T11:31:53.163561Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2022-10-02T11:31:53.163648Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.30'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server - GPL.

Launch Guacamole Server Container

Now, run the following command to start the Guacamole server container:

docker run --name guacamole-server -d guacamole/guacd

You can check the container logs using the following command:

docker logs --tail 10 guacamole-server

You will get the following output:

guacd[7]: INFO:	Guacamole proxy daemon (guacd) version 1.4.0 started
guacd[7]: INFO:	Listening on host 0.0.0.0, port 4822

To check the running container, use the following command:

docker ps

You will get the following output:

CONTAINER ID   IMAGE                COMMAND                  CREATED          STATUS                             PORTS                       NAMES
51b2efdab0db   guacamole/guacd      "/bin/sh -c '/usr/lo…"   26 seconds ago   Up 25 seconds (health: starting)   4822/tcp                    guacamole-server
c7a9309eac20   mysql/mysql-server   "/entrypoint.sh mysq…"   3 minutes ago    Up 3 minutes (healthy)             3306/tcp, 33060-33061/tcp   guacamoledb

Launch Guacamole Client Container

You can also start the Guacamole client container with the following command:

docker run --name guacamole-client --link guacamole-server:guacd --link guacamoledb:mysql -e MYSQL_DATABASE=guacdb -e MYSQL_USER=guacadmin -e MYSQL_PASSWORD=password -d -p 80:8080 guacamole/guacamole

Next, verify the running container with the following command:

docker ps

You should see the following output:

CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS                                 PORTS                                   NAMES
d4034a72bb69   guacamole/guacamole   "/opt/guacamole/bin/…"   58 seconds ago       Up 57 seconds                          0.0.0.0:80->8080/tcp, :::80->8080/tcp   guacamole-client
51b2efdab0db   guacamole/guacd       "/bin/sh -c '/usr/lo…"   About a minute ago   Up About a minute (health: starting)   4822/tcp                                guacamole-server
c7a9309eac20   mysql/mysql-server    "/entrypoint.sh mysq…"   5 minutes ago        Up 5 minutes (healthy)                 3306/tcp, 33060-33061/tcp               guacamoledb

At this point, the Guacamole container is started and listens on port 80. You can check it with the following command:

ss -altnp | grep :80

You will get the following output:

LISTEN 0      4096         0.0.0.0:80        0.0.0.0:*    users:(("docker-proxy",pid=4006,fd=4))   
LISTEN 0      4096            [::]:80           [::]:*    users:(("docker-proxy",pid=4013,fd=4))   

Access Apache Guacamole Dashboard

You can now access the Apache Guacamole web interface using the URL http://your-server-ip/guacamole. You should see the Guacamole login screen:

Apacje Guacamole Remote Desktop

Provide the default credentials:

User: guacadmin

Password: guacadmin

Then, click on the Login button. You should see the Guacamole dashboard on the following screen:

Connection manager

Conclusion

Congratulations! you have successfully installed the Apache Guacamole server and client using Docker on Ubuntu 22.04 server. You can now create a new connection and access the remote server via a web browser. Feel free to ask me if you have any questions.

Share this page:

Suggested articles

1 Comment(s)

Add comment

Comments

By: Srikumar Srinivasan at: 2022-11-02 13:41:43

Works great by exuting line by line, but where can I find snippet for the docker-compose.yml for this article.