Open salimfadhley opened 5 years ago
Can you clarify what exactly you are missing? I believe the documentation in https://github.com/docker-library/docs/tree/master/adminer contains all the custom environment variables.
I am trying to define the Adminer connection in my docker-compose
file.
The only env
documented is ADMINER_DEFAULT_SERVER=mysql
Is this the only env
available to configure? Is this supposed to be the entire engine params?
Is this the only
env
available to configure?
As documented here you can also configure the style and plugins: https://github.com/docker-library/docs/tree/master/adminer
Is this supposed to be the entire engine params?
This is the only this that can be configured about the login and it's only there, because the default of localhost
is absolutely useless in the context of Docker. If you'd like an automated login have a look at #13.
for local development and easy of onboarding developers (using docker to achieve that goal) how can we pass plugins through via the docker-compose
file?
You'll need to either bind mount the plugin (or plugin configuration) into the container or compile it into a customer Dockerfile.
I don't know docker-compose and thus don't know whether there's an easier solution.
I am trying to define the Adminer connection in my docker-compose file.
i feel like this was left unnoticed in this issue since this is the actual reason i'm writing here right now.
to give you a small insight in how docker-compose works..
it magically links containers together and ensures they are started in correct order. it also does watchdog stuff.
now to kinda reflect what users like us desire:
version: '3.7'
networks:
magic:
services:
db:
image: postgres:12.2
restart: unless-stopped
networks:
- magic
environment:
POSTGRES_USER: $DB_USER
POSTGRES_PASSWORD: $DB_PASS
volumes:
- ./postgresql/data:/var/lib/postgresql/data
adminer:
image: adminer:4.7.6
restart: unless-stopped
networks:
- magic
depends_on:
- db
ports:
- 127.0.0.55:8080:8080
environment:
ADMINER_DEFAULT_SERVER: db
ADMINER_DEFAULT_USER: $DB_USER
ADMINER_DEFAULT_PASSWORD: $DB_PASS
ADMINER_DEFAULT_TYPE: postgresql
ADMINER_DEFAULT_PORT: 5432
ADMINER_DEFAULT_DB: magic
actual application:
...
why is it so hard to specify these defaults..
one might say "oh no but it's unsafe. don't do that"
i might reply: "oh no. you cannot access 127.0.0.55 anyways so why you bother"
lol. just stumbled across this abandoned repository: https://github.com/michalhosna/adminer-docker
to give you a small insight in how docker-compose works..
I am aware of what docker-compose is on a high level. “Not knowing” is rather “Never used”.
why is it so hard to specify these defaults..
It's out of scope for this image which attempts to provide a “packaged Adminer”. The only bit that modifies the inner workings of Adminer is the replacement of the localhost
default value. The remaining modifications do not touch Adminer itself, but rather create a symlink (style) or preconfigure the Adminer plugin array.
one might say "oh no but it's unsafe. don't do that"
Yes, I consider hardcoding the credentials unsafe, because it's too easy to misconfigure.
@TimWolla I agree that being able to assign those settings, be it in environment variables or in a configuration file would be great. I already do that with phpMyAdmin and MySQL and it works great. I found adminer and found it great too, and it's very cool that it can connect to other databases aside from MySQL. But having to enter login and other stuff would be a pain in my case (especially when handling more than 1 server).
The adminer service would be accessible only through a a private network and authenticated with basic auth, and we prefer to use the credentials of the basic auth for our private services (not only adminer) which are easier to rotate passwords (it's just a file) instead of having to rotate passwords on a per service basis, which would be much more complex and error prone when automating. We also use a protection at the reverse proxy layer against CSRF. Furthermore, the credentials to the database would be mostly read-only. So, I don't think it would be unsafe in our case.
Yes, I consider hardcoding the credentials unsafe, because it's too easy to misconfigure.
In our use case we use ansible to automate the server deployment, the docker-compose
file is generated from a template and the .env
file that will have the password assigned is also created dynamically (and have the correct permissions) with variables coming from a trusted source, with the password encrypted in the source, so it's not hardcoded.
For me environment variables like @GottZ used would be really useful! If there is already a way of doing that using a file I haven't found.
I'm not saying that it must be done just because of my use case, I'm just giving my 2 cents, but it seems there are more people with the same request, so I came here to give a feedback.
Looking for something else I stumbled with this issue :smile:
I agree with Tim on this one that hardcoding credentials on files is unsafe.
Adminer is a web based management system for different databases done in PHP.
Saying that, what I do is, if I'm tired to enter the credentials at the login page all the time, I just save them with the browser option to remember credentials that is far more secure that having them around on a file.
Just my two cents :wink:
Being able to configure servers / plugins / credentials by using environment variables is just an absolute standard in the docker / kubernetes world, this is not unsafe, hardcoding here is a docker compose problem not an adminer one.
@pollier I'm aware of the the concept of using environment variables to pass credentials and in the context of Kubernetes this might be safely done, because the are not directly exposed to the user and can be changed in a central location.
But Kubernetes is not the only way this Docker image is going to be consumed. I'm seeing and using this primarily as a development tool, because IMO one should not poke around in a production database manually, but properly reviewed scripts / Ansible Playbooks / whatever.
Further different consumers have different needs and Adminer contains a plugin system that allows you to configure the authentication to your needs. Here's a non-core plugin that should be able to do the trick: https://github.com/giofreitas/one-click-login. You can access environment variables in PHP using $_ENV['stuff']
.
Anything that I'll build in the image will cause limitations for someone and diverge the image from the stock Adminer experience.
Yes, I consider hardcoding the credentials unsafe, because it's too easy to misconfigure.
Does that mean some people use adminer to access their database in production? I've always though adminer was only used locally to access a test database (with only mocked up data in it).
@cglacet
Does that mean some people use adminer to access their database in production?
Reading the comments above and also the other issues that are created in this repository: Yes, they do.
In fact for a local test database that is not reachable via the Internet the request to store credentials probably would be less important, because a username / password combination of root:root
would be acceptable from a security perspective and it would also be easy enough to type in quickly.
these environments are not working.
are they implemented in this docker image of adminer? or they will be implemented in future ?
ADMINER_DEFAULT_USER: $DB_USER
ADMINER_DEFAULT_PASSWORD: $DB_PASS
ADMINER_DEFAULT_TYPE: msqyl
@mtariqsajid They are variables that a user above posted as a request (example), I don't think the docker image supports it, and I don't know if it will support (it is what this issue is about tough).
user above p
they should support this it will much easy to set adminer with multiple docker images for development
As I explained many times before I won't be supporting these environment variables. I've explained possible solutions if you want to use these for your specific use-case.
I think this issue should be closed then (if the feature will not be implemented).
Can we at least get
ADMINER_DEFAULT_USER: $DB_USER
ADMINER_DEFAULT_TYPE: msqyl
?
Not allowing configuration of the password is an argument I can understand, even though I don't agree. But db type and user are not security sensitive (talking about the default postgres user in a dev env here), and would already solve most of the inconveniences I have with this Docker image.
I guess the better path forward would be to request on the upstream Adminer repo to read config from environment variables. Requesting it here for just the docker image, for me seems to be the wrong place.
However, I agree that the readme here should describe which env vars it adds, and what ways there are to configure upstream Adminer via env vars. (Even in case the latter currently is "none".)
Here's my dilemma. I need to be able to view, review and edit database content in initial development. docker-compose.yml test:
version: "3.8"
services:
mysql_db:
image: mysql:latest
ports:
- 3307:3307
environment:
- MYSQL_ROOT_PASSWORD=secret
volumes:
- ./mysql_db_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
environment:
PMA_HOST: mysql_db
PMA_USER: root
PMA_PASSWORD: secret
ports:
- 8081:80
adminer_container:
image: adminer:latest
environment:
ADMINER_DEFAULT_SERVER: mysql_db
ADMINER_DESIGN: galkaev
ADMINER_PASSWORD: secret
ADMINER_USERNAME: root
ports:
- 8080:8080
volumes:
mysql_db_data: {}
I understand the security issues. Try this for yourself. docker-compose up -d
. Then http://localhost:8080 (for adminer) http://localhost:8081 (for phpmyadmin)
Phpmyadmin works great, right out of the box. Adminer, No go.
This failure to populate login/password seems to be a sales pitch (for those of us who are admittedly often busy) the use of phpmyadmin instead of adminer. My focus needs to remain on coding a solution to the clients need not one off customizations of what should be standard tooling for my team. Keep it simple, make it work. Am I looking at this wrong?
By the way. Don't mean to be demeaning or ungrateful to Tim and the folks that support this repo. They've obviously put in a whole lot of work. Many thanks. I'm just frustrated that this one miss degrades the entire effort to use this amazing package. And that just drives me crazy. Again, many thanks to Tim.
@zipzit
Adminer, No go.
Indeed. Unfortunately the main Adminer repo is not open for issues, and their forum is cumbersome. Nevertheless, the request for easy server config via environment variables is a feature request best sent to upstream, i.e. Adminer itself, not for this docker wrapper.
@TimWolla Considering how often this feature is requested here, I think it's even worth explaining in the readme, where to beg for this feature.
However, I agree that the readme here should describe which env vars it adds, and what ways there are to configure upstream Adminer via env vars. (Even in case the latter currently is "none".)
@mk-pmb Feel free to propose changes as a PR over in docker-library/docs and simply ping me so I can review them.
I think it's sufficiently explained though, all the available configuration knobs are documented and what's not documented isn't there. Pretty simple.
Keep it simple, make it work. Am I looking at this wrong?
@zipzit Not sure if you are looking at this wrong. Let me give a different PoV, though: I'm keeping this image simple by not adding a large number of additional configuration knobs you have to think about when setting up this image.
Additionally upstream Adminer's Number 1 priority is “Security”. Providing database credentials to anyone able to access Adminer does not really fit in there.
Maybe Adminer simply isn't for you? If phpMyAdmin with its configurability better solves your requirements/problems, then I recommend to use phpMyAdmin.
@agates4 Thanks for that recommendation!
@TimWolla In case SqlPad turns out useful for local development with prefilled login, should I add that to the docs PR as well?
@TimWolla In case SqlPad turns out useful for local development with prefilled login, should I add that to the docs PR as well?
I'd rather not reference any external products/alternatives, especially products that are not available as an official Docker Image.
Turns out for my use case (initial software development of a new application), VSCode has a plugin that enables simple queries to mySQL. Reference.... No Adminer, no Phpmyadmin, one less container. No excessive security worries. Less is more.
No offense intended. Again many thanks to the Adminer team for an intriguing product.
@TimWolla
As I explained many times before I won't be supporting these environment variables. I've explained possible solutions if you want to use these for your specific use-case.
It might help to document those possible solutions.
This works for me when trying to increase upload limits using docker-compose: https://github.com/TimWolla/docker-adminer/issues/36#issuecomment-967527831
@TimWolla I do certainly appreciate your security concerns. I would like to propose that you add a section in the README that declares that there is one and only one Environment Variable that can be adjusted: ADMINER_DEFAULT_SERVER
As an option as well, perhaps you could also state something like: For all those that only want this for local development and will not be using this on anything other than localhost we suggest you use https://github.com/wodby/adminer
I've explained possible solutions if you want to use these for your specific use-case.
can you please tell us where we can read those possible solutions ?
I ended up using a different docker image and it does everything we need for local development:
adminer:
image: michalhosna/adminer # https://github.com/michalhosna/adminer-docker
restart: always
environment:
ADMINER_DRIVER: pgsql
ADMINER_USERNAME: debug
ADMINER_PASSWORD: debug
ADMINER_AUTOLOGIN: 1
ADMINER_SERVER: ${COMPOSE_PROJECT_NAME}-postgresql
ADMINER_DB: ${COMPOSE_PROJECT_NAME}
ADMINER_NAME: ${COMPOSE_PROJECT_NAME}
ports:
- "127.0.0.1:8084:8080"
depends_on:
postgresql:
condition: service_healthy
The addition of the 127.0.0.1
is important to make sure that if you are at a coffee shop or whatever that you are scoping access down to your local access only.
@jensenbox this looks crazily similar to my proposal from 3 years ago in this issue here.
@TimWolla please don't take this too personal but your world-view on containers in this issue seems a little flawed. most production deployments have some kind of ingress management with application and route specific permission grants to it's users. for example, you won't be able to access my router at home without going through my authenticator first. a friend of mine with an account on my authenticator will also not get into my router but will be able to access several other resources that I've granted to their account.
user access control and role based access control are topics, that are rarely transparent to applications in deployment. especially ones like phpmyadmin, adminer and so on. This is a good thing. Why would the Application even need to care about the complicated topic of authentication, if a Service in front of it is already taking care of it.
Also... if you setup something like adminer or phpmyadmin or what ever up in production, it has one specific reason: The application accessing the database might not have a properly built admin interface. This is mostly the case in non-consultant work, like internal applications, or applications without non-programmers as administrators.
access control is out of scope for adminer. it cannot deal with saml, oauth, webauthn, reverse proxy authentication and so on.. so why enforce something as low as password authentication? in some cases, it might not even be able to access the authentication server for backend login confirmation if permissions were set restrictive af..
for example, it would be much wiser to have a popup like this in adminer:
if default credentials were supplied, rather than strictly preventing the use of default credentials at all.
saying that default credentials are a bad thing is your opinion but not a fact, that reflects common use-cases. suggesting to use root:root in test environments is also opinionated and in many ways bad advice. suggesting to write your own docker image to include a plugin that does this automatically is also opinionated and leaves a bad taste of outdated images behind, because someone got to trigger a image re-build when upstream updates, and not everyone has sufficient tooling for that.
so.. that's my 2 cents.
don't feel attacked by this please.
I just can't stand enforcement of password authentication in a world that has moved beyond passwords at this point.
I'm not taking this personal, but I naturally disagree. I'm not going to link to the heaploads of articles of improperly secured databases out in the Internet. By posting this comment on this issue tracker you're likely already above-average knowledge with regard to “how to properly run servers and how to perform authentication”. However naturally not everyone is above-average and from experience any type of warning message is ignored anyway. I don't want to be a contributing factor to databases being exposed and PII stolen and sold on the dark net. Defaults matter and in the end I'm going to be blamed for shipping something with insecure defaults.
Also, keep in mind that I do not develop Adminer itself.
I agree that it shouldn't be the image authors' responsibility to make these decisions. Rather, docker should supply its users with an easy (easier?) way to monkey-patch the relevant parts of an image.
what about docker secrets then? https://docs.docker.com/compose/use-secrets/
That would still require quite a bit of custom code to be written and careful checking that the secrets do not leak anywhere.
If anyone picks this up, maybe add this to the documentation to satisfy the common feature request raised in this issue:
In case you prefer to have auto-login for your dev deployments, you'll need to create your own Dockerfile deriving from this one. Simply put these two files in a folder and reference it using e.g. build:context:
in your docker-compose:
my-adminer-image/Dockerfile
FROM adminer
RUN mv /var/www/html/index.php /var/www/html/entrypoint.php
COPY index.php /var/www/html/
my-adminer-image/index.php
<?php
if(!count($_GET)) {
$_POST['auth'] = [
'server' => $_ENV['ADMINER_DEFAULT_SERVER'] ?? 'db',
'username' => $_ENV['ADMINER_USERNAME'] ?? 'root',
'password' => $_ENV['ADMINER_PASSWORD'] ?? '',
'driver' => $_ENV['ADMINER_DRIVER'] ?? 'server',
'db' => $_ENV['ADMINER_DB'] ?? '',
];
}
require('./entrypoint.php');
(source: https://steampixel.de/auto-login-to-adminer/ ; adjusted to be configurable)
Example Usage:
version: "3.2"
services:
db:
image: mariadb
environment:
MARIADB_DATABASE=mydb
MARIADB_ROOT_PASSWORD=root
adminer:
build:
context: my-adminer-image
environment:
- ADMINER_DEFAULT_SERVER=db
- ADMINER_DRIVER=server # server is adminer-speak for 'mysql'
- ADMINER_USERNAME=root
- ADMINER_PASSWORD=root
- ADMINER_DB=mydb
ports:
- 8080:8080
depends_on:
- db
Cheers!
Since full Adminer's presetting is something requested from time to time and the maintainer won't support this at all, here's a workaround that doesn't require building custom images.
This injects a patched index.php that allows passwordless login to SQLite and takes default values from environment variables. Note that the passwordless login patch will be triggered whenever ADMINER_DEFAULT_DRIVER
is set to sqlite
or sqlite2
.
The docker-compose file injection currently doesn't work for configuring plugins with parameters because of this bug, that overwrites files within plugins-enabled folder, so don't bother trying until it gets patched.
docker-compose.yml
:
version: "3.0"
name: adminer
services:
adminer-sqlite:
image: adminer
environment:
ADMINER_DEFAULT_DRIVER: sqlite # server=mysql, pgsql, sqlite, sqlite2, oracle, mssql, mongo, elastic
ADMINER_DEFAULT_DB: /data/database.db
ADMINER_DEFAULT_SERVER:
ADMINER_DEFAULT_USERNAME:
ADMINER_DEFAULT_PASSWORD:
ADMINER_DESIGN: dracula # https://www.adminer.org/#extras
ADMINER_PLUGINS: tables-filter table-structure edit-textarea dump-json # https://www.adminer.org/en/plugins/
volumes: [datavolume:/data]
ports: [127.0.0.1:8091:8080]
configs: [{ source: adminer-index.php, target: /var/www/html/index.php }]
configs:
adminer-index.php:
# Patched version of index.php to set default values for adminer and to
# allow passwordless login whenever ADMINER_DEFAULT_DRIVER is sqlite.
content: |
<?php
namespace docker {
function adminer_object() {
require_once('plugins/plugin.php');
class Adminer extends \AdminerPlugin {
function _callParent($$function, $$args) {
if ($$function === 'loginForm') {
ob_start();
$$return = \Adminer::loginForm();
$$form = ob_get_clean();
$$driver = $$_ENV["ADMINER_DEFAULT_DRIVER"] ?: "server";
$$server = $$_ENV["ADMINER_DEFAULT_SERVER"] ?: "db";
$$username = $$_ENV["ADMINER_DEFAULT_USERNAME"];
$$password = $$_ENV["ADMINER_DEFAULT_PASSWORD"];
$$db = $$_ENV["ADMINER_DEFAULT_DB"];
$$form = preg_replace('/ name="auth\[server\]" value="(.*)"/', ' name="auth[server]" value="' . $$server . '"', $$form);
$$form = str_replace(' id="username" value="" ', ' id="username" value="' . $$username . '" ', $$form);
$$form = str_replace('name="auth[db]" value=""', 'name="auth[db]" value="' . $$db . '" ', $$form);
$$form = str_replace('type="password"', 'type="password" value="' . $$password . '"', $$form);
$$form = preg_replace('/<option value="(.*)" selected/', '/<option value="$$1"/', $$form);
$$form = preg_replace('/<option value="' . $$driver . '"/', '<option value="' . $$driver . '" selected', $$form);
echo $$form;
return $$return;
}
return parent::_callParent($$function, $$args);
}
}
$$plugins = [];
foreach (glob('plugins-enabled/*.php') as $$plugin) {
$$plugins[] = require($$plugin);
}
class AdminerSoftware extends Adminer {
function login($$login, $$password) {
return substr($$_ENV["ADMINER_DEFAULT_DRIVER"], 0, 6) == 'sqlite' ? true : parent::login($$login, $$password);
}
}
return new AdminerSoftware($$plugins);
}
}
namespace {
if (basename($$_SERVER['DOCUMENT_URI'] ?? $$_SERVER['REQUEST_URI']) === 'adminer.css' && is_readable('adminer.css')) {
header('Content-Type: text/css');
readfile('adminer.css');
exit;
}
function adminer_object() {
return \docker\adminer_object();
}
require('adminer.php');
}
Thanks for the idea! However, in this thread it will be hard to find soon. Would you mind moving it to a new thread? Then your headline would be easier to search. And ideally you could use Gist to share the code, so people can have a download button next to the file.
This would make it much easier to get started with the container: A simple list of each environment variable, along with it's intended use.
Thanks