Guacamole is a clientless remote desktop gateway for VNC, RDP, and SSH protocols. Using this you can connect to any of your computers via a web browser. It can be installed as a standalone application or as a docker image. Docker installation is the easiest to install and maintain.
Here we shall see how to install Guacamole as a docker container and connect to a remote machine quickly.
Installing Guacamole Docker container
Make sure you have installed Portainer & Docker before proceeding. We will add a docker stack of Guacamole and MariaDB using Portainer.
1. Create a new bridge network for your containers to communicate. Alternatively you can do this on Poratainer too, under Networks -> Add network.
docker network create -d bridge intranet
2. On Portainer, add a new stack with name Guacamole. Leave the Build method as Web Editor.
3. Copy the below compose file content into the Web editor. You can customize if needed and deploy.
version: "2"
services:
db:
image: mariadb
restart: unless-stopped
container_name: mariadb
environment:
- MYSQL_ROOT_PASSWORD=rootpw
- MYSQL_DATABASE=guacamole_db
- MYSQL_USER=guacamole_user
- MYSQL_PASSWORD=guacamolepw
volumes:
- /opt/container/mariadb:/var/lib/mysql
ports:
- 3306:3306
hostname: mariadb
networks:
- intranet
guacd:
image: guacamole/guacd
container_name: guacd
hostname: guacd
restart: always
volumes:
- /opt/container/guacamole/guacd:/etc/guacamole
ports:
- 4822:4822
networks:
- intranet
guacamole:
image: guacamole/guacamole
container_name: guacamole
hostname: guacamole
restart: always
volumes:
- /opt/container/guacamole/guacamole:/etc/guacamole
ports:
- 8080:8080
environment:
- GUACD_HOSTNAME=guacd
- GUACD_PORT=4822
- GUACAMOLE_HOME=/etc/guacamole
- MYSQL_HOSTNAME=mariadb
- MYSQL_PORT=3306
- MYSQL_DATABASE=guacamole_db
- MYSQL_USER=guacamole_user
- MYSQL_PASSWORD=guacamolepw
networks:
- intranet
networks:
intranet:
external:
name: intranet
4. Guacamole needs the tables configured in the MariaDB docker container to work. The below two commands accomplish that. After running the commands in the linux shell of your host (not container), make sure to restart all three containers.
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
docker exec -i mariadb mysql -u root --password=rootpw guacamole_db < initdb.sql
5. Then, go to http://localhost:8080/guacamole/ and login with default credentials guacadmin:guacadmin. Now you have successfully installed Guacamole on docker.

9 comments
Hey I tried this self hosted solution out, a couple things to note. The docker compose script expects the network “intranet” to already be created, if not you’ll get an error message about intranet being depracated. Secondly I while I was able to get around the first issue by manually running “docker network create intranet”, there was a second issue with the guacamole container that I was unable to solve, it starts up fine but the logs just repeat this message over and over again.
“cp: cannot stat ‘/data/.’: No such file or directory”
Ah! Thanks for taking the time to comment here. I fixed the script and updated it here.
Cheers it fixed! One last note it’s http://localhost:3080/guacamole/ instead of 8080 to get to the webadmin panel not sure if you wanted to use that port or not. Doesn’t matter to me.
Thanks again! I think that was a typo. I fixed the port mapping.
Would it be possible to add a bit on how to enable TOTP for 2fa? Thanks!
To activate this on my instance i added these lines :
guac:
image: guacamole/guacamole:1.0.0
restart: always
ports:
– “8081:8080”
volumes:
– ./totp:/tmp/totp
On your host you must have downloaded the plugin ;
root@CloudCompose:~/guacamole/guacamole-docker-compose# ls
data docker-compose.yml init totp
Then you should be good
Below command fails:
docker exec -i mariadb mysql -u root –password=rootpw guacamole_db < initdb.sql
and should be:
docker exec -i mariadb mariadb -u root –password=rootpw guacamole_db < initdb.sql
The guacamole_db is then created properly but nevertheless I get below error when trying to access : http://localhost:8080/guacamole/
An error has occurred and this action cannot be completed. If the problem persists, please notify your system administrator or check your system logs.
I can see this error multiple times in the logs:
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
09:33:48.587 [http-nio-8080-exec-7] WARN o.a.g.e.AuthenticationProviderFacade – The "mysql" authentication provider has encountered an internal error which will halt the authentication process. If this is unexpected or you are the developer of this authentication provider, you may wish to enable debug-level logging. If this is expected and you wish to ignore such failures in the future, please set "skip-if-unavailable: mysql" within your guacamole.properties.
09:33:48.590 [http-nio-8080-exec-7] ERROR o.a.g.rest.RESTExceptionMapper – Unexpected internal error:
### Error querying database. Cause: java.sql.SQLException: Unknown system variable 'transaction_isolation'
### The error may exist in org/apache/guacamole/auth/jdbc/user/UserMapper.xml
### The error may involve org.apache.guacamole.auth.jdbc.user.UserMapper.selectOne
### The error occurred while executing a query
### Cause: java.sql.SQLException: Unknown system variable 'transaction_isolation'
When using an older mariadb image (mariadb:10.11), it works. So it must be something that has changed in one ore more of the latest image versions of mariadb
Final command fails with:
OCI runtime exec failed: exec failed: unable to start container process: exec: “mysql”: executable file not found in $PATH: unknown