Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgres alpine #119

Closed
wants to merge 3 commits into from
Closed

Postgres alpine #119

wants to merge 3 commits into from

Conversation

ncopa
Copy link
Contributor

@ncopa ncopa commented Jan 20, 2016

No description provided.

@ncopa
Copy link
Contributor Author

ncopa commented Jan 20, 2016

I don't know if we want variants as subdirectory under each version or add the alpine variant as its own version. I went for flatter structure here as it seems simpler.

@tianon
Copy link
Member

tianon commented Jan 29, 2016

As far as structure goes, I'd prefer to stay consistent with the other repos and stick the variants as subdirectories.

Relevant diff: (for easier review)

--- Dockerfile  2016-01-28 12:44:39.611831695 -0800
+++ /dev/fd/63  2016-01-29 13:01:40.760263290 -0800
@@ -1,40 +1,71 @@
 # vim:set ft=dockerfile:
-FROM debian:jessie
+FROM alpine:3.3

 # explicitly set user/group IDs
-RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres
-
-# grab gosu for easy step-down from root
-RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
-RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \
-   && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture)" \
-   && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture).asc" \
-   && gpg --verify /usr/local/bin/gosu.asc \
-   && rm /usr/local/bin/gosu.asc \
-   && chmod +x /usr/local/bin/gosu \
-   && apt-get purge -y --auto-remove ca-certificates wget
+#RUN adduser -S -G postgres -u 999 postgres

 # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default
-RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
-   && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
 ENV LANG en_US.utf8

 RUN mkdir /docker-entrypoint-initdb.d

-RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8
-
 ENV PG_MAJOR 9.5
-ENV PG_VERSION 9.5.0-1.pgdg80+2
+ENV PG_VERSION 9.5.0
+ENV PG_SHA256 f1c0d3a1a8aa8c92738cab0153fbfffcc4d4158b3fee84f7aa6bfea8283978bc

-RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list

-RUN apt-get update \
-   && apt-get install -y postgresql-common \
-   && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \
-   && apt-get install -y \
-       postgresql-$PG_MAJOR=$PG_VERSION \
-       postgresql-contrib-$PG_MAJOR=$PG_VERSION \
-   && rm -rf /var/lib/apt/lists/*
+# configure options taken from:
+# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5
+RUN set -x \
+   && apk add --no-cache --virtual .build-deps \
+       su-exec \
+       bash \
+       bison \
+       curl \
+       flex \
+       gcc \
+       krb5-dev \
+       libc-dev \
+       libedit-dev \
+       libxml2-dev \
+       libxslt-dev \
+       make \
+       openldap-dev \
+       openssl-dev \
+       perl \
+       perl-dev \
+       python3-dev \
+       tcl-dev \
+       util-linux-dev \
+       zlib-dev \
+   && curl -fSL "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" -o postgresql.tar.bz2 \
+   && echo "$PG_SHA256  postgresql.tar.bz2" | sha256sum -c - \
+   && mkdir -p /usr/src \
+   && tar -jxf postgresql.tar.bz2 -C /usr/src \
+   && rm postgresql.tar.bz2 \
+   && cd /usr/src/postgresql-$PG_VERSION \
+   && ./configure \
+       --enable-integer-datetimes \
+       --enable-tap-tests \
+       --enable-thread-safety \
+       --prefix=/usr/local \
+       --with-libedit-preferred \
+       --with-openssl \
+       --with-uuid=e2fs \
+   && make -j$(getconf _NPROCESSORS_ONLN) world \
+   && make install-world \
+   && make -C contrib install \
+   && runDeps="$( \
+       scanelf --needed --nobanner --recursive /usr/local \
+           | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
+           | sort -u \
+           | xargs -r apk info --installed \
+           | sort -u \
+   )" \
+   && apk add --virtual .postgresql-rundeps $runDeps su-exec \
+   && apk del .build-deps \
+   && cd / && rm -rf /usr/src/postgresql-* /usr/local/include/* \
+   && find /usr/local -name '*.a' -delete

 RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql
--- docker-entrypoint.sh    2016-01-28 12:44:39.608831780 -0800
+++ /dev/fd/63  2016-01-29 13:02:19.922170280 -0800
@@ -1,5 +1,4 @@
-#!/bin/bash
-set -e
+#!/bin/sh -e

 set_listen_addresses() {
    sedEscapedValue="$(echo "$1" | sed 's/[\/&]/\\&/g')"
@@ -11,12 +10,12 @@
    chmod 700 "$PGDATA"
    chown -R postgres "$PGDATA"

-   chmod g+s /run/postgresql
-   chown -R postgres /run/postgresql
+   chmod g+s /var/run/postgresql
+   chown -R postgres /var/run/postgresql

    # look specifically for PG_VERSION, as it is expected in the DB dir
    if [ ! -s "$PGDATA/PG_VERSION" ]; then
-       gosu postgres initdb
+       su-exec postgres initdb

        # check password first so we can output the warning before postgres
        # messes it up
@@ -47,7 +46,7 @@

        # internal start of server in order to allow set-up using psql-client       
        # does not listen on TCP/IP and waits until start finishes
-       gosu postgres pg_ctl -D "$PGDATA" \
+       su-exec postgres pg_ctl -D "$PGDATA" \
            -o "-c listen_addresses=''" \
            -w start

@@ -77,17 +76,13 @@
        for f in /docker-entrypoint-initdb.d/*; do
            case "$f" in
                *.sh)  echo "$0: running $f"; . "$f" ;;
-               *.sql) 
-                   echo "$0: running $f"; 
-                   psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < "$f"
-                   echo 
-                   ;;
+               *.sql) echo "$0: running $f"; psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < "$f" && echo ;;
                *)     echo "$0: ignoring $f" ;;
            esac
            echo
        done

-       gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop
+       su-exec postgres pg_ctl -D "$PGDATA" -m fast -w stop
        set_listen_addresses '*'

        echo
@@ -95,7 +90,7 @@
        echo
    fi

-   exec gosu postgres "$@"
+   exec su-exec postgres "$@"
 fi

 exec "$@"

@sylus
Copy link

sylus commented Feb 9, 2016

I was curious about the change from gosu to su-exec? Is that indeed the recommended way when working with alpine?

@tianon
Copy link
Member

tianon commented Feb 9, 2016 via email

@sylus
Copy link

sylus commented Feb 9, 2016

Thanks @tianon I also share your concerns about the switch as also prefer consistency. However happy that the switch will only happen after parity tests. Thx for taking the time, I know your busy!

@mmarzantowicz
Copy link

Why don't you use upstream package instead of building from source? Alpine Linux already has postgres package available (https://pkgs.alpinelinux.org/package/main/x86_64/postgresql). Are there any reasons for not using that package? I'm just curious.

@ncopa
Copy link
Contributor Author

ncopa commented Feb 15, 2016

rebased with variants in subdirs

@sylus
Copy link

sylus commented Feb 18, 2016

Wrong queue. Moved issue over to php alpine.

@ncopa
Copy link
Contributor Author

ncopa commented Feb 18, 2016

@sylus i assume your comment was supposed for the php-alpine pull request and not the postgres.

But yes looks like you are right. fix is on the way.

@sylus
Copy link

sylus commented Feb 18, 2016

@ncopa yes sorry about that :) thx so much for taking a look :)

@gittycat
Copy link

Could this commit be merged soon?
alpine:3.3 is now the default base image for docker, as per shykes which means that it's likely going to be present on the image cache on each vm/host.

@yosifkit
Copy link
Member

@gittycat, We are looking into it. As for the "switching the Docker official image library from ubuntu to Alpine" as stated by Solomon that is misleading: most are based on Debian and there is no "switching" to Alpine, the default is still Debian. What we are doing is adding Alpine Linux based variants so that if a user wants a slimmer base they can use the Alpine based images with the caveats linked on their descriptions like golang.

@tianon
Copy link
Member

tianon commented Mar 18, 2016

What's Alpine's backport policy for things like su-exec? Any way we could get su-exec 0.2 into Alpine 3.3, or do we need to wait for Alpine 3.4?

@tianon
Copy link
Member

tianon commented Mar 18, 2016

The other easy option I see would be to just stick with gosu for now, and switch to su-exec once Alpine 3.4 comes out. 👍

@ncopa
Copy link
Contributor Author

ncopa commented Mar 21, 2016

The backport policy is "don't break things for existing users". I don't think there are many su-exec users, and the 0.2 release can be considered as a bug-fix. I'll cherry-pick it for 3.3-stable.

@ncopa
Copy link
Contributor Author

ncopa commented Mar 21, 2016

su-exec-0.2 was pushed to alpine 3.3-stable

@zot24
Copy link

zot24 commented Apr 14, 2016

What's the crack for this PR guys!? are we gonna merge it? or is it on hold for now? it will be nice to see a Alpine flavour for Postgres cheers!

@ptman
Copy link

ptman commented Apr 18, 2016

At least the PR would probably need to be updated from 9.5.0 to 9.5.2

@sylus
Copy link

sylus commented Apr 19, 2016

Excited for this to get in ^_^

@hovsater
Copy link

Would love to see this get merged. 👍 Any updates on getting this merged with upstream?

@sylus
Copy link

sylus commented May 12, 2016

I have been using ncopa's build for a while now without issue. If that data point helps. ^_^

@ptman
Copy link

ptman commented May 12, 2016

Is the on disk format unchanged? Can I mount the same data to the alpine based image or do I have to do a dump and restore?

@mmarzantowicz
Copy link

I was also using @ncopa's image and it works for me. What are the reasons there is still no alpine image of postgresql? Is this project dead or Docker is planing to do things the other way? Maybe there are some issues to be resolved?

@ncopa
Copy link
Contributor Author

ncopa commented May 23, 2016

@tianon whats the blocker here?

@Starefossen
Copy link

I'm with @ptman, what are the implications for existing postgres users? Is this a breaking change in some way? What about existing initd script files in downstream images?

@deinspanjer
Copy link

deinspanjer commented Jun 21, 2016

With the release of Alpine 3.4, the creation of a postgres image is now even simpler. I wrote my own one-off build at https://github.com/deinspanjer/docker-postgres95-alpine34, but the code might be of interest to @ncopa for this PR as well.

@tianon
Copy link
Member

tianon commented Jun 27, 2016

I think the main concern here would be the same as the comment from @yosifkit over in MariaDB/mariadb-docker#53 (comment):

Yeah, mariadb, mysql, and percona use Debian packages that are provided by upstream directly, so I think it is unwise that we provide something that they do not support.

Since we're not building from source (per upstream's recommendations), do we have anything from them noting that they do officially support Alpine, and that compiling from source is the recommended means by which we should obtain the latest releases of PostgreSQL in such an environment?

If we can't find something suitable which makes it clear upstream will support this configuration, it would be prudent to post on the pgsql-pkg-docker mailing list to solicit comments (upstream is reasonably active there).

@sylus
Copy link

sylus commented Jun 27, 2016

Just for my own edification and potentially others what exactly are the main benefits of preferring packages over building from source? Is it mostly around sizing issues / complexity? I have always found particularly for alpine + musl that building from source seems to be the recommended workflow. Though am no doubt wrong :)

I only ask because I saw other official images like nginx build from source for alpine: https://github.com/nginxinc/docker-nginx/blob/master/stable/alpine/Dockerfile

@tianon
Copy link
Member

tianon commented Jun 27, 2016 via email

@tianon
Copy link
Member

tianon commented Jun 27, 2016 via email

@tianon
Copy link
Member

tianon commented Jun 27, 2016 via email

@sylus
Copy link

sylus commented Jun 28, 2016

Ah! Thank you so much for this, greatly appreciate you taking the time to help explain ^_^

@sylus
Copy link

sylus commented Jun 30, 2016

I have posted the question in the mailing list @ https://www.postgresql.org/list/pgsql-pkg-docker/2016-06/

@austinnichols101
Copy link

FYI - No issues encountered so far in my local testing with this PR + alpine:3.4.

@blag
Copy link

blag commented Sep 28, 2016

I think the discussion around compiling from source vs. installing Alpine's packages is rather overblown, because this is the only patch Alpine 3.3 applies (full package info here):

--- ./src/bin/initdb/initdb.c.orig  2013-09-09 14:38:21.712409752 +0000
+++ ./src/bin/initdb/initdb.c   2013-09-09 14:40:19.453755379 +0000
@@ -3652,14 +3652,6 @@
    strlcpy(bin_dir, argv[0], sizeof(bin_dir));
    get_parent_directory(bin_dir);

-   printf(_("\nSuccess. You can now start the database server using:\n\n"
-            "    %s%s%spostgres%s -D %s%s%s\n"
-            "or\n"
-            "    %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
-      QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
-          QUOTE_PATH, pgdata_native, QUOTE_PATH,
-      QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
-          QUOTE_PATH, pgdata_native, QUOTE_PATH);
-
+   printf(_("\nSuccess.\n\n"));
    return 0;
 }

and this is the only patch Alpine 3.4 applies (full package info here):

diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index feeff9e..e6a4536 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -3641,10 +3641,7 @@ main(int argc, char *argv[])
    strlcpy(bin_dir, argv[0], sizeof(bin_dir));
    get_parent_directory(bin_dir);

-   printf(_("\nSuccess. You can now start the database server using:\n\n"
-            "    %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
-      QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
-          QUOTE_PATH, pgdata_native, QUOTE_PATH);
+   printf(_("\nSuccess.\n\n"));

    return 0;
 }

Neither patch should impact how PostgreSQL operates.

I didn't see any response on the Postgres mailing list to their support for compiling from source vs. using Alpine packages, so I assume they don't have an opinion either way.

Personally, for what it's worth, I would prefer to use the Alpine packages, both because they make building images faster and they would be more aware of how their package integrates with the rest of their OS.

@sylus
Copy link

sylus commented Oct 3, 2016

Agreed I don't think we are going to be getting a response from the mailing list. I'd really like this issue to be closed though as it has been stalled for quite a while. Would be great to have an alpine based postgresql image as it would be my last debian derived container to remove.

@austinnichols101
Copy link

Reduced size is a nice benefit, but I think the biggest benefit is the reduced attack surface. IOW, better security because there are fewer things that need to be patched.

@blag
Copy link

blag commented Oct 3, 2016

Alpine also uses PaX, which helps prevent some buffer overflow attacks and direct code execution, grsecurity patches, and compiles their packages as position-independent executables with stack-smashing protection.

So when used for web development, this makes Postgres running on Alpine more difficult to successfully attack than, say, your run-of-the-mill Debian distribution.

@ncopa
Copy link
Contributor Author

ncopa commented Oct 3, 2016

You will only benefit from PaX when you run a kernel with the grsecurity patch. If you run the alpine postgresql package in docker but not use grsecurity patched kernel on the host, then you'll not have the PaX benefits.

@blag
Copy link

blag commented Oct 3, 2016

Oh right, I forgot containerization != virtualization. 😆

But the PIE executables and the stack-smashing protection should still work.

@sylus
Copy link

sylus commented Oct 4, 2016

So potential next steps given the above?

I really don't want to see this issue queue stalled for another few months. Especially since the P.R. works great.

@austinnichols101
Copy link

I suspect it would need to be updated to support postgres 9.6 now that it has been released.

This was referenced Oct 25, 2016
@yosifkit
Copy link
Member

Ok, I did a little research on what operating systems are supported by Postgres (since that is my major reservation in adding an Alpine Linux based version). I found that "PostgreSQL can be expected to work on these operating systems: Linux (all recent distributions)" source, so I think it is fair to move this forward. (cc @tianon)

It looks like #210, is just a copy and update of this PR, so @tianon and I will review the two PRs and hopefully get something merged soon. 🎉

@tianon
Copy link
Member

tianon commented Nov 3, 2016

After playing a bit, I can see exactly why you didn't include Perl, Python, or TCL support... This PR clocks in an image at ~43.54MB, but with Perl, Python, and TCL enabled, it goes up to ~166.5MB. 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.