Is there a better way to do this?

Hello,
I’ve been following these instructions to create a docker-compose.yml for Apache Guacamole: Chapter 3. Installing Guacamole with Docker

So far, I got it down to 2 steps:

  1. docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
  2. docker-compose up -d

My docker-compose.yml:

---
version: '3.6'
services:
  mariadb:
    image: mariadb:latest
    environment:
      MYSQL_ROOT_PASSWORD: rootpw
      MYSQL_DATABASE: guacdb
      MYSQL_USER: guacuser
      MYSQL_PASSWORD: guacuserpw
    volumes:
      - ${PWD}/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql
      - mysql_data:/var/lib/mysql
  guacd:
    image: guacamole/guacd
    depends_on:
    - mariadb
  guacamole:
    image: guacamole/guacamole
    depends_on:
    - guacd
    environment:
      GUACD_HOSTNAME: guacd
      MYSQL_HOSTNAME: mariadb
      MYSQL_DATABASE: guacdb
      MYSQL_USER: guacuser
      MYSQL_PASSWORD: guacuserpw
    ports:
    - '8080:8080'
volumes:
  mysql_data:

Is there a better way to do this? Is it possible to incorporate step 1 into the docker-compose.yml file? If I have to get Guacamole going on multiple hosts, it sure would be nice to just launch one ‘docker-compose up’ command (i.e. no step 1 init script) and done.

Thanks in advance for any ideas or suggestions.

Regards,
Ed A

A custom database image comes to mind. Generate the script once, and copy that into your own database image. Something like:

FROM mariadb:latest
COPY initdb.sql docker-entrypoint-initdb.d/initdb.sql

Build and tag using docker build -t <your-docker-id>/guacamole-mariadb ., push to your own Docker Hub repository using docker push <your-docker-id>/guacamole-mariadb, and use that image in the Compose file.

But, the above still needs you to generate the initdb.sql file one time. Now, the documentation says:

Alternatively, you can use the SQL scripts included with the database authentication.

That’s quite vague. But on the Docker Hub repo it says:

Alternatively, you can use the SQL scripts included with guacamole-auth-jdbc.

If those are somehow usable then you could ADD them from GitHub directly:

FROM mariadb:latest

ADD https://raw.githubusercontent.com/apache/guacamole-client/0.9.10-incubating/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql /docker-entrypoint-initdb.d/

ADD https://raw.githubusercontent.com/apache/guacamole-client/0.9.10-incubating/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql /docker-entrypoint-initdb.d/

I’ve no idea if MariaDB would pick up the two scripts 001-create-schema.sql and 002-create-admin-user.sql. But the .d for directory in the directory name docker-entrypoint-initdb.d suggests it does. Let us know! (Aside: the file dates will be set to Jan 1, 1970.)

And are these indeed the same files? Peeking into /opt/guacamole/bin/initdb.sh tells you more. The relevant part seems to be:

docker run --rm guacamole/guacamole cat /opt/guacamole/bin/initdb.sh
...
cat /opt/guacamole/mysql/schema/*.sql

So, it concatenates all .sql files into a single file. A quick look suggests those are the same files indeed:

docker run --rm guacamole/guacamole /bin/sh -c "ls -l /opt/guacamole/mysql/schema/*.sql"

-rw-r--r-- 1 root root 20174 Oct 17 00:52 /opt/guacamole/mysql/schema/001-create-schema.sql
-rw-r--r-- 1 root root  2876 Oct 17 00:52 /opt/guacamole/mysql/schema/002-create-admin-user.sql

Knowing that initdb.sh uses those files (but still not sure if MariaDB would pick up multiple files in that folder; let us know!), I’d prefer:

FROM mariadb:latest

COPY --from=guacamole/guacamole /opt/guacamole/mysql/schema/*.sql /docker-entrypoint-initdb.d/

Alternatively, rather than creating your own MariaDB image, you may be able to share the initialization volume between Guacamole and MariaDB. For Guacamole map it to /opt/guacamole/mysql/schema/ and for MariaDB to /docker-entrypoint-initdb.d/. But that would very much rely on the startup order, to ensure Docker copies the files from Guacamole into the empty volume on first start. Sounds unreliable, especially as you actually want to start MariaDB first.

Or make Guacamole create the tables itself, rather than relying on the MariaDB initialization. Other users will be happy with a merge request to achieve that!

Aside: I wonder what happens if Guacamole is updated. Would it work with an outdated initdb.sql? Would it change the database schema when needed?

It is kind of odd that the entrypoint script of guacamole does not take care of it…

Also the documentation is not realy up to date, as it uses some rather outdated docker techniques…

Though, what about the lazy way? Ever considered to create the sql file(s) once and add them to the same (git) repo as the docker-compose.yml file?

Is there any magic to make Compose pass the SQL files to (the container of) the default MariaDB image?

I’ve always thought Compose just orchestrated images, but does not provide means to, say, add files to some volume (to make the files available to the standard images).

Ah, you’re suggesting to still rely on the existing bind mount in the volumes: definition, just making the generated initdb.sql available in the same folder as the Compose file after a git clone:

volumes:
  - ${PWD}/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql

Yes, that will work. :sunglasses:

1 Like

Thank you for your suggestions. To summarize, there are two solutions:

  1. Create a pre-initialized DB image and push it to a Docker repo. Then modify docker-compose file to use new DB image
  2. Include both files (init script and docker-compose) in a Git repo. Then a ‘git clone’ and run the docker-compose.

I’m going to try both solutions. The lazy one :slight_smile: is quick and easy. The pre-init DB solution is nice to help me learn more.

Thanks again!

-Ed