TimWolla / docker-adminer

Database management in a single PHP file
https://hub.docker.com/_/adminer/
157 stars 69 forks source link

Could you update the image documentation to include all of the environment variables and what they do? #52

Open salimfadhley opened 5 years ago

salimfadhley commented 5 years ago

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

TimWolla commented 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.

agates4 commented 4 years ago

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?

TimWolla commented 4 years ago

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.

agates4 commented 4 years ago

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?

TimWolla commented 4 years ago

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.

GottZ commented 4 years ago

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"

GottZ commented 4 years ago

lol. just stumbled across this abandoned repository: https://github.com/michalhosna/adminer-docker

TimWolla commented 4 years ago

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.

lucasbasquerotto commented 4 years ago

@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.

edomato commented 3 years ago

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:

pollier commented 3 years ago

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.

TimWolla commented 3 years ago

@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.

cglacet commented 3 years ago

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).

TimWolla commented 3 years ago

@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.

mtariqsajid commented 3 years ago

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
lucasbasquerotto commented 3 years ago

@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).

mtariqsajid commented 3 years ago

user above p

they should support this it will much easy to set adminer with multiple docker images for development

TimWolla commented 3 years ago

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.

lucasbasquerotto commented 3 years ago

I think this issue should be closed then (if the feature will not be implemented).

DasSkelett commented 3 years ago

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.

mk-pmb commented 2 years ago

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.

mk-pmb commented 2 years ago

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".)

zipzit commented 2 years ago

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.

mk-pmb commented 2 years ago

@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.

agates4 commented 2 years ago

For my use case, because of this lack of docs, I switched to SqlPad

TimWolla commented 2 years ago

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.

mk-pmb commented 2 years ago

@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 commented 2 years ago

@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.

zipzit commented 2 years ago

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.

fnagel commented 2 years ago

@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

jensenbox commented 1 year ago

@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

mtariqsajid commented 1 year ago

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 ?

jensenbox commented 1 year ago

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.

GottZ commented 1 year ago

@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: image 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.

TimWolla commented 1 year ago

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.

mk-pmb commented 1 year ago

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.

GottZ commented 1 year ago

what about docker secrets then? https://docs.docker.com/compose/use-secrets/

TimWolla commented 1 year ago

That would still require quite a bit of custom code to be written and careful checking that the secrets do not leak anywhere.

DaDummy commented 7 months ago

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!

lincolnthalles commented 6 months ago

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.

Auto-login with docker-compose (all drivers)

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');
      }
mk-pmb commented 6 months ago

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.