├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── Vagrantfile └── scripts ├── first_run.sh ├── normal_run.sh └── start.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Postgresql (http://www.postgresql.org/) 2 | 3 | FROM phusion/baseimage:0.9.13 4 | MAINTAINER Ryan Seto 5 | 6 | # Ensure we create the cluster with UTF-8 locale 7 | RUN locale-gen en_US.UTF-8 && \ 8 | echo 'LANG="en_US.UTF-8"' > /etc/default/locale 9 | 10 | # Disable SSH (Not using it at the moment). 11 | RUN rm -rf /etc/service/sshd /etc/my_init.d/00_regen_ssh_host_keys.sh 12 | 13 | # Install the latest postgresql 14 | RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \ 15 | apt-get update && \ 16 | DEBIAN_FRONTEND=noninteractive \ 17 | apt-get install -y --force-yes \ 18 | postgresql-9.3 postgresql-client-9.3 postgresql-contrib-9.3 && \ 19 | /etc/init.d/postgresql stop 20 | 21 | # Install other tools. 22 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y pwgen inotify-tools 23 | 24 | # Clean up APT when done. 25 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 26 | 27 | # Cofigure the database to use our data dir. 28 | RUN sed -i -e"s/data_directory =.*$/data_directory = '\/data'/" /etc/postgresql/9.3/main/postgresql.conf 29 | # Allow connections from anywhere. 30 | RUN sed -i -e"s/^#listen_addresses =.*$/listen_addresses = '*'/" /etc/postgresql/9.3/main/postgresql.conf 31 | RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.3/main/pg_hba.conf 32 | 33 | EXPOSE 5432 34 | ADD scripts /scripts 35 | RUN chmod +x /scripts/start.sh 36 | RUN touch /firstrun 37 | 38 | # Add daemon to be run by runit. 39 | RUN mkdir /etc/service/postgresql 40 | RUN ln -s /scripts/start.sh /etc/service/postgresql/run 41 | 42 | # Expose our data, log, and configuration directories. 43 | VOLUME ["/data", "/var/log/postgresql", "/etc/postgresql"] 44 | 45 | # Use baseimage-docker's init system. 46 | CMD ["/sbin/my_init"] 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ryan Seto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Substitute your own docker index username, if you like. 2 | DOCKER_USER=paintedfox 3 | 4 | # Change this to suit your needs. 5 | NAME:=postgresql 6 | USER:=super 7 | PASS:=$(shell pwgen -s -1 16) 8 | DATA_DIR:=/tmp/postgresql 9 | PORT:=127.0.0.1:5432 10 | 11 | RUNNING:=$(shell docker ps | grep $(NAME) | cut -f 1 -d ' ') 12 | ALL:=$(shell docker ps -a | grep $(NAME) | cut -f 1 -d ' ') 13 | DOCKER_RUN_COMMON=--name="$(NAME)" -p $(PORT):5432 -v $(DATA_DIR):/data -e USER="$(USER)" -e PASS="$(PASS)" $(DOCKER_USER)/postgresql 14 | 15 | all: build 16 | 17 | build: 18 | docker build -t="$(DOCKER_USER)/postgresql" . 19 | 20 | run: clean 21 | mkdir -p $(DATA_DIR) 22 | docker run -d $(DOCKER_RUN_COMMON) 23 | 24 | bash: clean 25 | mkdir -p $(DATA_DIR) 26 | docker run -t -i $(DOCKER_RUN_COMMON) /sbin/my_init -- bash -l 27 | 28 | # Removes existing containers. 29 | clean: 30 | ifneq ($(strip $(RUNNING)),) 31 | docker stop $(RUNNING) 32 | endif 33 | ifneq ($(strip $(ALL)),) 34 | docker rm $(ALL) 35 | endif 36 | 37 | # Destroys the data directory. 38 | deepclean: clean 39 | sudo rm -rf $(DATA_DIR) 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-postgresql 2 | 3 | A Dockerfile that produces a container that will run [PostgreSQL][postgresql]. 4 | 5 | [postgresql]: http://www.postgresql.org/ 6 | 7 | ## Image Creation 8 | 9 | This example creates the image with the tag `paintedfox/postgresql`, but you can 10 | change this to use your own username. 11 | 12 | ``` 13 | $ docker build -t="paintedfox/postgresql" . 14 | ``` 15 | 16 | Alternately, you can run the following if you have *make* installed... 17 | 18 | ``` 19 | $ make 20 | ``` 21 | 22 | You can also specify a custom docker username like so: 23 | 24 | ``` 25 | $ make DOCKER_USER=paintedfox 26 | ``` 27 | 28 | ## Container Creation / Running 29 | 30 | The PostgreSQL server is configured to store data in `/data` inside the 31 | container. You can map the container's `/data` volume to a volume on the host 32 | so the data becomes independant of the running container. There is also an 33 | additional volume at `/var/log/postgresql` which exposes PostgreSQL's logs. 34 | 35 | This example uses `/tmp/postgresql` to store the PostgreSQL data, but you can 36 | modify this to your needs. 37 | 38 | When the container runs, it creates a superuser with a random password. You 39 | can set the username and password for the superuser by setting the container's 40 | environment variables. This lets you discover the username and password of the 41 | superuser from within a linked container or from the output of `docker inspect 42 | postgresql`. 43 | 44 | If you set DB=database_name, when the container runs it will create a new 45 | database with the USER having full ownership of it. 46 | 47 | ``` shell 48 | $ mkdir -p /tmp/postgresql 49 | $ docker run -d --name="postgresql" \ 50 | -p 127.0.0.1:5432:5432 \ 51 | -v /tmp/postgresql:/data \ 52 | -e USER="super" \ 53 | -e DB="database_name" \ 54 | -e PASS="$(pwgen -s -1 16)" \ 55 | paintedfox/postgresql 56 | ``` 57 | 58 | Alternately, you can run the following if you have *make* installed... 59 | 60 | ``` shell 61 | $ make run 62 | ``` 63 | 64 | You can also specify a custom port to bind to on the host, a custom data 65 | directory, and the superuser username and password on the host like so: 66 | 67 | ``` shell 68 | $ sudo mkdir -p /srv/docker/postgresql 69 | $ make run PORT=127.0.0.1:5432 \ 70 | DATA_DIR=/srv/docker/postgresql \ 71 | USER=super \ 72 | PASS=$(pwgen -s -1 16) 73 | ``` 74 | 75 | ## Connecting to the Database 76 | 77 | To connect to the PostgreSQL server, you will need to make sure you have 78 | a client. You can install the `postgresql-client` on your host machine by 79 | running the following (Ubuntu 12.04LTS): 80 | 81 | ``` shell 82 | $ sudo apt-get install postgresql-client 83 | ``` 84 | 85 | As part of the startup for PostgreSQL, the container will generate a random 86 | password for the superuser. To view the login in run `docker logs 87 | ` like so: 88 | 89 | ``` shell 90 | $ docker logs postgresql 91 | POSTGRES_USER=super 92 | POSTGRES_PASS=b2rXEpToTRoK8PBx 93 | POSTGRES_DATA_DIR=/data 94 | Starting PostgreSQL... 95 | Creating the superuser: super 96 | 2014-02-07 03:30:55 UTC LOG: database system was interrupted; last known up at 2014-02-01 07:06:21 UTC 97 | 2014-02-07 03:30:55 UTC LOG: database system was not properly shut down; automatic recovery in progress 98 | 2014-02-07 03:30:55 UTC LOG: record with zero length at 0/17859E8 99 | 2014-02-07 03:30:55 UTC LOG: redo is not required 100 | 2014-02-07 03:30:55 UTC LOG: database system is ready to accept connections 101 | 2014-02-07 03:30:55 UTC LOG: autovacuum launcher started 102 | ``` 103 | 104 | Then you can connect to the PostgreSQL server from the host with the following 105 | command: 106 | 107 | ``` shell 108 | $ psql -h 127.0.0.1 -U super template1 109 | ``` 110 | 111 | Then enter the password from the `docker logs` command when prompted. 112 | 113 | ## Linking with the Database Container 114 | 115 | You can link a container to the database container. You may want to do this to 116 | keep web application processes that need to connect to the database in 117 | a separate container. 118 | 119 | To demonstrate this, we can spin up a new container like so: 120 | 121 | ``` shell 122 | $ docker run -t -i --link postgresql:db ubuntu bash 123 | ``` 124 | 125 | This assumes you're already running the database container with the name 126 | *postgresql*. The `--link postgresql:db` will give the linked container the 127 | alias *db* inside of the new container. 128 | 129 | From the new container you can connect to the database by running the following 130 | commands: 131 | 132 | ``` shell 133 | $ apt-get install -y postgresql-client 134 | $ psql -U "$DB_ENV_USER" \ 135 | -h "$DB_PORT_5432_TCP_ADDR" \ 136 | -p "$DB_PORT_5432_TCP_PORT" 137 | ``` 138 | 139 | If you ran the *postgresql* container with the flags `-e USER=` and `-e 140 | PASS=`, then the linked container should have these variables available 141 | in its environment. Since we aliased the database container with the name 142 | *db*, the environment variables from the database container are copied into the 143 | linked container with the prefix `DB_ENV_`. 144 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 8 | config.vm.box = "phusion/ubuntu-14.04-amd64" 9 | 10 | config.vm.provision "docker", images: ["paintedfox/postgresql"] do |d| 11 | d.run "paintedfox/postgresql", 12 | args: "--name=postgresql -v /vagrant/path/to/your/folder:/var/lib/postgresql -p 5432:5432 ", 13 | daemonize: true 14 | end 15 | 16 | config.vm.network "forwarded_port", guest: 5432, host: 5432 17 | end 18 | -------------------------------------------------------------------------------- /scripts/first_run.sh: -------------------------------------------------------------------------------- 1 | USER=${USER:-super} 2 | PASS=${PASS:-$(pwgen -s -1 16)} 3 | 4 | pre_start_action() { 5 | # Echo out info to later obtain by running `docker logs container_name` 6 | echo "POSTGRES_USER=$USER" 7 | echo "POSTGRES_PASS=$PASS" 8 | echo "POSTGRES_DATA_DIR=$DATA_DIR" 9 | if [ ! -z $DB ];then echo "POSTGRES_DB=$DB";fi 10 | 11 | # test if DATA_DIR has content 12 | if [[ ! "$(ls -A $DATA_DIR)" ]]; then 13 | echo "Initializing PostgreSQL at $DATA_DIR" 14 | 15 | # Copy the data that we generated within the container to the empty DATA_DIR. 16 | cp -R /var/lib/postgresql/9.3/main/* $DATA_DIR 17 | fi 18 | 19 | # Ensure postgres owns the DATA_DIR 20 | chown -R postgres $DATA_DIR 21 | # Ensure we have the right permissions set on the DATA_DIR 22 | chmod -R 700 $DATA_DIR 23 | } 24 | 25 | post_start_action() { 26 | echo "Creating the superuser: $USER" 27 | setuser postgres psql -q <<-EOF 28 | DROP ROLE IF EXISTS $USER; 29 | CREATE ROLE $USER WITH ENCRYPTED PASSWORD '$PASS'; 30 | ALTER USER $USER WITH ENCRYPTED PASSWORD '$PASS'; 31 | ALTER ROLE $USER WITH SUPERUSER; 32 | ALTER ROLE $USER WITH LOGIN; 33 | EOF 34 | 35 | # create database if requested 36 | if [ ! -z "$DB" ]; then 37 | for db in $DB; do 38 | echo "Creating database: $db" 39 | setuser postgres psql -q <<-EOF 40 | CREATE DATABASE $db WITH OWNER=$USER ENCODING='UTF8'; 41 | GRANT ALL ON DATABASE $db TO $USER 42 | EOF 43 | done 44 | fi 45 | 46 | if [[ ! -z "$EXTENSIONS" && ! -z "$DB" ]]; then 47 | for extension in $EXTENSIONS; do 48 | for db in $DB; do 49 | echo "Installing extension for $db: $extension" 50 | # enable the extension for the user's database 51 | setuser postgres psql $db <<-EOF 52 | CREATE EXTENSION "$extension"; 53 | EOF 54 | done 55 | done 56 | fi 57 | 58 | rm /firstrun 59 | } 60 | -------------------------------------------------------------------------------- /scripts/normal_run.sh: -------------------------------------------------------------------------------- 1 | pre_start_action() { 2 | : # No-op 3 | } 4 | 5 | post_start_action() { 6 | : # No-op 7 | } 8 | -------------------------------------------------------------------------------- /scripts/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Starts up postgresql within the container. 3 | 4 | # Stop on error 5 | set -e 6 | 7 | DATA_DIR=/data 8 | 9 | if [[ -e /firstrun ]]; then 10 | source /scripts/first_run.sh 11 | else 12 | source /scripts/normal_run.sh 13 | fi 14 | 15 | wait_for_postgres_and_run_post_start_action() { 16 | # Wait for postgres to finish starting up first. 17 | while [[ ! -e /run/postgresql/9.3-main.pid ]] ; do 18 | inotifywait -q -e create /run/postgresql/ >> /dev/null 19 | done 20 | 21 | post_start_action 22 | } 23 | 24 | pre_start_action 25 | 26 | wait_for_postgres_and_run_post_start_action & 27 | 28 | # Start PostgreSQL 29 | echo "Starting PostgreSQL..." 30 | setuser postgres /usr/lib/postgresql/9.3/bin/postgres -D /etc/postgresql/9.3/main 31 | --------------------------------------------------------------------------------