Docker-compose, run crash commands when starting containers

Hello,

I’m new to CrateDB and am currently testing it out for a possible use case.
As I’m using docker-compose to spin up my single-node (for now) container, I’d like to add more customization right away instead of having to do this manually by hand afterwards through bash every time on a new host.

What I’d like to do is to run docker-compose up -d with the following:

  1. spin up a single-node container
  2. After it’s up & running, automatically run “crash” and create a standard table with predefined columns
  3. also use “crash” to create a new user with password and grant all privileges
  4. after that change the auth.host_based.config method to “password”…and restart container?

my test docker-compose.yml file:

  cratedb:
    image: crate:4.7.1
    container_name: cratedb
    #environment:
    #  - CRATE_DOCKER_CRATEWEB_SUPERUSER_USERNAME=admin <-- this doesn't work..?
    #  - CRATE_DOCKER_CRATEWEB_SUPERUSER_PASSWORD=pass <-- this doesn't work..?
    ports:
      - 4200:4200
      - 5432:5432
    restart: always
    volumes:
      - cratedb_data:/data
      - cratedb_config:/crate/config
    command: ["crate",
              "-Cnetwork.host=_local_, _site_",
              "-Cauth.host_based.enabled=true",
              "-Cauth.host_based.config.0.user=crate",
              "-Cauth.host_based.config.0.method=trust",
              "-Cauth.host_based.config.1.user=admin",
              "-Cauth.host_based.config.1.method=trust",
              "-Cdiscovery.type=single-node",
              # "crash", "CREATE TABLE IF NOT EXISTS test2 (ts TIMESTAMP, lifecounter INTEGER, fields OBJECT)"] <-- this line doesn't work  

Above file only works for running the container. However, creating a user either through env or running crash through “command” won’t work. I’m still learning a lot about docker, so there must be a better way to go about this.
Has anyone already tried to run crash “scripts” while creating&running a docker container at startup for ease of automation at startup? (unless I’m looking at this the wrong way…)

P.S.: only alternatives I know of is

  • creating a 2nd container which accesses the desired container through bash to run such specific crash commands
  • or to preconfigure and copy the volumes to each new host, thus giving a new cratedb container the necessary starting template user and table.
1 Like

Hi @neshorg,

I think your alternatives are valid approaches to solve this. An additonal option would be to write a setup-script (e.g. ./crate-setup.sh) which executes docker-compose up -d and afterwards execute the additional steps (e.g. docker compose exec cratedb crash -c '...')

1 Like

Hello @jayeff,

Thank you for the suggestion. That one hasn’t crossed my mind yet, but will surely work as this is basically indeed what I’m doing manually each time the container starts for the first time through the container-cli.

However, a part of me still believes/feels like this should be possible directly from my compose-file? This is what I’ve tried so far after my original post above:

  1. moving all crate settings from command to the crate.yml file and mounting that to the file inside the container. This meant leaving the “command” option free to only call my crash lines. Correcting my earlier line I used:
command: ["crash", "-c", "CREATE TABLE IF NOT EXISTS test2 (ts TIMESTAMP, lifecounter INTEGER, fields OBJECT)"]

→ this doesn’t work and returns me with an error in the logs of “crash-cli” trying to parse the 3rd argument from “command” as options/flags instead of an argument for the already placed flag “-c”.


2. So next up was placing my crash commands in a seperate .sh script-file and calling this file in “command”. My script-file and command:

command: ["../../template.sh"]

template.sh (using a tutorial as reference):

#!/bin/bash

UPDATE_QUERY=$(cat << QUERY
  CREATE TABLE IF NOT EXISTS test2 (ts TIMESTAMP, lifecounter INTEGER, fields OBJECT);
QUERY
)

crash -c '${UPDATE_QUERY}' > /dev/null

→ However, this gives me another crash-cli error “CONNECT ERROR”, meaning it couldn’t even connect via the “crash” command alone, thus never getting to the “-c” and its argument…I think.


I might be missing something in my steps above, but otherwise your option would be the best alternative at the moment. I’ll evaluate this a little more and will update this post with a chosen solution later on.

For anyone wondering, I’ve chosen @jayeff 's solution as this brings me one important advantage:

  • It enables me to use the separate script-file on the first-time while setting up a new host, whereas trying to integrate it in a single docker-compose file would make it call the setup-commands every time I run docker-compose up -d for any modifications in the future, like upgrading the image version and so on.

My current host is running a windows-OS, so i created a simple batch file:

:: use the cd command if the batch file doesn`t reside in the same directory as the compose file
::cd "C:\Docker\MyStack"

docker-compose up -d

:: I had to use a timeout in order to let the cratedb service finish starting up, otherwise I`d get a crash-cli error
TIMEOUT 10

docker-compose exec cratedb crash -c "CREATE TABLE IF NOT EXISTS test2 (ts TIMESTAMP, lifecounter INTEGER, fields OBJECT)"

:: If needed, then use the "pause" command to view any returning errors from crash-cli for debugging, otherwise CMD exits & closes the window automatically
::pause
2 Likes

I believe here you miss a comma (,) after "-c". But even with this comma it wouldn’t work. See below for why.

The problem is that once you remove “crate” command you now never start CrateDB on your container. Crash can’t connect if CrateDB isn’t running :sweat_smile:

Good catch, I changed it right away. Somehow I got a typo in there while creating my reply back then.

I see, so then it would’ve been impossible since everything in “command” gets concatenated allowing you to only call the “crate” command with all its arguments and making a combination with “crash” impossible, right?

However, with the separate batch script file right now I’m not even using the “command” or “entrypoint” options at all.
So “crate” always gets called somehow in the background with or without mentioning it in the docker file? Otherwise my batch script should’ve failed when calling upon “crash” later on to create my template-table?

You maybe could hack around it but I wouldn’t recommend this. E.g. if you start crate in the background and then execute further commands. This is rather hacky and may harbors other problems (e.g. typically stopping the container stops the cmd process. here your would circumvent this and instead kill the process). Also as you mentioned all this command would be executed every time you run docker compose up which is maybe not what you want.

Correct, docker-compose command allows you to override the command as specified in the Dockerfile

command overrides the the default command declared by the container image
Compose specification | Docker Documentation

If you do not declare command it will fall back to the one defined in the crate docker image which is also crate
https://hub.docker.com/layers/crate/library/crate/4.8.0/images/sha256-170490659b05a4a2644e65721e1fcd850e2a426c32a1b1552d018533f5da3fe2?context=explore

2 Likes