6

I'm new to Dancer, but I'm trying to configure it to work within a Docker container. As a result, I need to pick up my database settings from the environment.

In my case, I have DB_PORT_3306_TCP_ADDR, and DB_PORT_3306_TCP_PORT coming from Docker. Unfortunately, the Dancer::Plugin::Database module is erroring before I can change the database to use those variables.

use Dancer ':syntax';
use Dancer::Plugin::Database;

if ($ENV{DB_PORT_3306_TCP}) {## Connected via docker.
    database->({
        driver => 'mysql',
        username => 'username',
        password => 'password',
        host => $ENV{DB_PORT_3306_TCP_ADDR},
        port => $ENV{DB_PORT_3306_TCP_PORT},
        database => $ENV{DB_ENV_MYSQL_DATABASE},
    });
}

So the question is, is there a good way to configure Dancer from environment variables, instead of through static YAML?

Jack M.
  • 30,350
  • 7
  • 55
  • 67

2 Answers2

5

See Runtime Configuration in the Dancer::Plugin::Database docs:

You can pass a hashref to the database() keyword to provide configuration details to override any in the config file at runtime if desired, for instance:

my $dbh = database({ driver => 'SQLite', database => $filename });

You're adding a ->, which causes an error. The following should work:

use Dancer ':syntax';
use Dancer::Plugin::Database;

if ($ENV{DB_PORT_3306_TCP}) {## Connected via docker.
    database({
        driver => 'mysql',
        username => 'username',
        password => 'password',
        host => $ENV{DB_PORT_3306_TCP_ADDR},
        port => $ENV{DB_PORT_3306_TCP_PORT},
        database => $ENV{DB_ENV_MYSQL_DATABASE},
    });
}
Community
  • 1
  • 1
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
  • Great observation, and you're right. However, if I do as your code suggests, `database->quick_select(...)` yields an error: `Can't call method "quick_select" on an undefined`. Is there not a way to keep the `database` global? – Jack M. Nov 05 '14 at 22:27
  • Digging into the code for `Dancer::Plugin::Database::Core`, it looks like you can get the same connection handle on subsequent calls to `database` by passing the same hashref of settings: "The key to use to store this handle in `%handles`. This will be either the name supplied to `database()`, the hashref supplied to `database()` (thus, as long as the same hashref of settings is passed, the same handle will be reused) or `$def_handle` if `database()` is called without args" Unfortunately, passing around a hashref of settings is really no different from passing around a database handle. – ThisSuitIsBlackNot Nov 05 '14 at 23:06
  • You might play around with adding the connection settings to `config` and keeping track of them there: [Accessing configuration information from your app](https://metacpan.org/pod/Dancer::Cookbook#Accessing-configuration-information-from-your-app). Or simply creating a wrapper for the `database` function that passes in the correct settings. – ThisSuitIsBlackNot Nov 05 '14 at 23:14
  • @JackM. `database()` returns handler, AFAIR, so you could save it into var like `$dbh = database( { driver => ... } )` – w.k Jan 24 '16 at 23:44
0

At the beginning of your lib/myapp.pm, after module loading, add :

setting('plugins')->{'Database'}->{'host'}='postgres';
setting('plugins')->{'Database'}->{'database'}=$ENV{POSTGRES_DB};
setting('plugins')->{'Database'}->{'username'}=$ENV{POSTGRES_USER};
setting('plugins')->{'Database'}->{'password'}=$ENV{POSTGRES_PASSWORD};

and keep static config (Driver, port) in config.yml

mick
  • 197
  • 3