Hacker News new | ask | show | jobs
by rcconf 4008 days ago
My apologies if I'm hijacking the original poster.

Does Docker handle multi-environment configuration management? For example: qa, stage and live have the same config files, but different values.

Currently we're using Ansible and we set variables for a specific environment, then we feed those variables into config files based on where we're deploying to (config files are not duplicated, only variables that feed into config files.)

All of our configuration is in git and we can quickly see and change it.

How does Docker handle this?

5 comments

This is not necessarily a part of the Docker specification, but here's a best practice followed by many apps running in Docker containers: http://12factor.net/config
This. Our most recent project was engineered to leverage Docker and Ansible in this manner.

We have a single playbook to deploy everything, i.e. deploy multiple (micro)services, heavily using docker images pulled from a private registry.

With a single playbook, we have multiple Ansible inventory / hosts file for each environment: QA, prod. Sensitive information / secrets are stored in Ansible-vault groupvar files. QA people have ssh access to their own machines, while Prod ops have their own separate ssh access and machines.

The playbook was refactored to heavily use roles, wherein config template files are dynamically setup using inputs from inventory vars and groupvars.

The roles are also topology independent, meaning a QA project cluster can actually be a single big VM with mocked DBs, while the Prod cluster can be spread across multiple machines.

Docker helped simplify the code deployment. Prior to deployment, docker images are built and tested by Jenkins first prior to pushing the images to the registry.

One way I've seen many people tackle this problem is to have the Dockerfile/image built in a more generic way, then the end of the Dockerfile kicks off an Ansible playbook (or some other lite CM tool) that will configure everything for the proper environment (e.g. change configuration and kick off a service, something along those lines).

Some will even go as far as using a CM tool to do the entire internal Dockerfile build, and the Dockerfile is just a wrapper around the CM tool. This does require more bloat inside the Docker image, as you need to have your CM tool or whatever other supporting files/scripts installed in the image, but it does make more complex scenarios much simpler.

> you need to have your CM tool or whatever other supporting files/scripts installed in the image

This pattern is maybe even more helpful than harmful, for making your dev environment more closely match production, when your final deploy target is not a docker container.

(You are obviously going to want to see those build scripts running in test, if not earlier; certainly once, before they should kick off in a production environment.) You could do more individual steps in the docker file, just like you could store your token credentials and database handles in the git repository. Neither way is "completely wrong" but there is a trade-off.

It sounds like you're reinventing a PaaS, which is a road many people go down when they build their devops environment from the ground up.

In the long run it's a bad idea: you wind up with a snowflake PaaS that only you maintain and only you can understand or extend. The amount of engineering effort behind Heroku, Cloud Foundry or OpenShift is enormous and you can get support on a high level.

I'm biased, because I work for Pivotal (who founded Cloud Foundry), but in my view rolling your own PaaS is a strategic error at this point.

Absolutely. This situation is handled by using Environment variables. Depending on the environment, I use environment variables to point services at different places (ie dedicated production database server vs my micro dev mysql container).
Remember that environment variables are visible to processes outside the container (i.e. users), if they have the same or higher privileged user. They are not a great place to store passwords or any other confidential information.
The environment of a process is only available to root or the same uid.

    vagrant@monitor:/proc$ sudo -u nginx cat 1779/environ
UPSTART_INSTANCE=runlevel=2UPSTART_JOB=rcTERM=linuxPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binRUNLEVEL=2PREVLEVEL=NUPSTART_EVENTS=runlevelPWD=/previous=N

It's not uncommon to allow users to sudo up to particular system users for commands, nor it is uncommon for compromised programs to give the attacker a shell as the user of the compromised program.

Anything owned by that user is vulnerable. A common problem which is typically resolved by reading a config file while root and downgrading to a lower privilege user. For example, you wouldn't want anyone who could become the nginx user to get the SSL key, or the password to your S3 bucket, or...

You do not give the nginx user sudo ability, and any user who has sudo is root, and should be treated as such.