Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Alpine based GoCD server Docker image. #42

Merged
merged 11 commits into from
Jul 14, 2016
Merged

Alpine based GoCD server Docker image. #42

merged 11 commits into from
Jul 14, 2016

Conversation

tpbrown
Copy link
Contributor

@tpbrown tpbrown commented Jul 5, 2016

~ 212MB image

Notable changes:

  • New Dockerfile (not erb) for Alpine
  • Installs via the zip package, and ignores most of the contents
  • Simplifies the volumes exposed (/config, /logs, /artifacts) and maps GoCD's directory structure into it
    -- This required some bootstrapping for the h2db bundles zips.

SERVER_STARTUP_ARGS="${SERVER_STARTUP_ARGS} ${JVM_DEBUG} ${GC_LOG} ${GO_SERVER_SYSTEM_PROPERTIES}"
SERVER_STARTUP_ARGS="${SERVER_STARTUP_ARGS} -Duser.language=en -Djruby.rack.request.size.threshold.bytes=30000000"
SERVER_STARTUP_ARGS="${SERVER_STARTUP_ARGS} -Duser.country=US -Dcruise.config.dir=$GO_CONFIG_DIR -Dcruise.config.file=$GO_CONFIG_DIR/gocd-server-config.xml"
sSERVER_STARTUP_ARGS="${SERVER_STARTUP_ARGS} -Dcruise.server.port=$GO_SERVER_PORT -Dcruise.server.ssl.port=$GO_SERVER_SSL_PORT"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sSERVER looks like a typo

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 6, 2016

Thanks @FredrikWendt -- I'll get that fixed.

@@ -0,0 +1,41 @@
# Build using : GO_VERSION=16.x.x-xxxx docker build -f Dockerfile.alpine-gocd-server -tag=alpine-gocd-server .
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe -tag should be --tag

@arvindsv
Copy link
Member

arvindsv commented Jul 7, 2016

I like this. We've talked about moving to alpine, and even tried it with agents and then went back on it. For the server, it makes more sense.

@zabil is taking care of the docker images these days. Maybe he can take a look. I'd merge this in and make it the default gocd/gocd-server template and go from there. We'd need to change the documentation on the docker hub page as well.

MAINTAINER GoCD <[email protected]>

# GoCD scripts used here work with ash -- bash not needed. Only git support is bundled.
RUN apk --no-cache add git
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get subversion, mercurial in there too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What % of installs are using them?

Subversion adds ~37M to the image size. Mercurial (while bad-ass!) is a whopping ~92M more.

I'd suggest keeping only git if my guesses on usage are anywhere near accurate. Those with other SCM needs could base off this and heir client.

If you're in agreement I can add some documentation (where?) describing how to use it as a base image.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're in agreement I can add some documentation (where?) describing how to use it as a base image.

Sounds good, I was under the assumption they'd be a few megs. I think adding a note somewhere in the README is a good start.

@zabil
Copy link
Contributor

zabil commented Jul 7, 2016

I had created one for agents via #34
I guess the same limitations don't apply to the server.

I'll merge it in once the subversion and mercurial packages are also installed.
Will look at how it works and consider modifying the build scripts to make this the default.

@arvindsv
Copy link
Member

arvindsv commented Jul 7, 2016

@zabil: Cool. Also, I forgot to mention. Once we change the build scripts, we need to change the template to make experimental builds possible. As mentioned in #41.

mkdir /config/db
unzip -qq /go-server/go.jar defaultFiles/h2db.zip defaultFiles/h2deltas.zip
unzip -qq defaultFiles/h2db.zip -d /config/db
unzip -qq defaultFiles/h2deltas.zip -d /config/db
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand right, /config/db can come from a volume. Shouldn't the unzip of h2deltas.zip to /config/db happen every time, and not just if /config/db does not exist? I mean, it's not part of bootstrapping. If it's not done every time, upgrades will fail. Every release can change h2deltas.zip. So, if you use a new docker image and get volumes from your data-only container, /config/db will be bind mounted and the ! -d /config/db check will be false, and the new deltas for this release won't be in place.

Once this is done: Across releases of GoCD, if we remove a file from h2deltas.zip, the old file will not get removed from /config/db/h2deltas, right? This might be a problem. Might want to think about cleaning up the dirs. I suspect this will be a problem with vanilla GoCD as well, and doesn't show up because we only ever add to h2deltas, and never remove from it. So, not very worried about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You know a ton more about this than me ;-) I just noticed that if 'db' existed and was empty GoCD didn't unzip h2deltas, etc. and would fail.

I'll make this unzip every time.

Re: removing files from the h2deltas -- switch it to a bundled [shallow] Git repo instead of a zip?

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 7, 2016

@zabil I think the primary difference with #34 is that GoCD server has a much narrower set of constraints. We only need Java, GoCD, and SCM client. All of those exist in Alpine.

Agents need access to an undetermined amount of dev toolchains. Some might work.. many won't as you found out :)

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 7, 2016

@arvindsv re experimental builds

If you move from ERB templates to outright Dockerfiles you can A) file for an 'Official' GoCD build on dockerhub, and B) offload docker build to Hub.

That's why I switched to using an ENV in the Alpine file. I'm using Docker Hub for image CI while working. (and it'd be easy to pass if your were running docker build in GoCD)

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 7, 2016

OK - I think that's it.

I'm likely to open another PR after this one to tidy up a few more operational aspects. Given that we're running in a container we can drop a ton of vars and make things simpler:

  • Extract autoDetectJavaExecutable() to common for both agent & server
  • Eliminate SERVER_*_MEM -- calculate -Xms -Xmx based on visible memory. Users set resource limits via docker run.
  • Eliminate *_PORT -- always 8153, 8154. Also user controlled via docker run.
  • Eliminate SERVER_WORK_DIR. Not user-visible, and running in container.
  • Eliminate YOURKIT
  • Eliminate pid file bits. Java is pid 1 (and appears to handle kill -3 properly, etc.)
  • Eliminate SERVER_LISTEN_HOST.

If you see any other low-hanging fruit please shout. :-)

@zabil
Copy link
Contributor

zabil commented Jul 7, 2016

We did look at using docker to automate builds, but the problem was having to check-in the docker files once the version changes to trigger a build.

Or do they have remote build triggers where I can pass the GO_VERSION as an environment variable?

@zuriar
Copy link

zuriar commented Jul 7, 2016

Hi there

Aravind has directed me here from the Google Group. I asked this question:

https://groups.google.com/forum/#!topic/go-cd/5AMoH3LlsjU

Basically, will it be possible to swap out the auto-generated keystore at /etc/go/keystore with a signed keystore? At present, the container starts up and over-writes any attempt at inserting the signed keystore from the Dockerfile build (or by way of volume mount).

Thanks
Hugh

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 7, 2016

Don't merge this -- getting backchannel feedback re: agent keys, and passing system properties.

Update:

  • agent key appears to be working as expected (at least in what I haven't pushed yet)
  • System properties are munged. It appears this is coming from the Ash shell Exhibits in both ash and bash. You can see the problem by looking at the sun.java.command property from /go/api/support -- the parameters aren't being parsed properly.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 7, 2016

@zuriar in looking at the code I do think you can do that.

If /config/etc/keystore exists then it won't create one.

@zuriar
Copy link

zuriar commented Jul 7, 2016

@tpbrown do you mean if /etc/go/keystore exists? Or did you really mean /config/etc/keystore?

I did try attaching a volume with the keystore in it to /etc/go but the server fails to start with:

docker run -it -v ~/certs/keystore:/etc/go/keystore -p 8154:8154 gocd/gocd-server

ERROR: Failed to start Go server. Please check the logs.
java.io.FileNotFoundException: /etc/go/truststore (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:146)
at org.eclipse.jetty.util.resource.FileResource.getInputStream(FileResource.java:290)
at org.eclipse.jetty.util.security.CertificateUtils.getKeyStore(CertificateUtils.java:43)
at org.eclipse.jetty.util.ssl.SslContextFactory.loadTrustStore(SslContextFactory.java:884)
at org.eclipse.jetty.util.ssl.SslContextFactory.doStart(SslContextFactory.java:274)

Appears to not be generating the truststore?

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 7, 2016

@zuriar Make sure you're using an image built from the PR. /config is an exposed volume. /etc/go links to /config/etc. See the Dockerfile for the details.

mkdir -p ./config/etc
cp ~/certs/keystore ./config/etc
docker run -it -v ${PWD}/config:/config -p 8153:8153  <imagename from docker build>

@zuriar
Copy link

zuriar commented Jul 7, 2016

@tpbrown thanks, I followed your instructions and built from the PR.

Even without then using the volume mapping the server just hangs on startup. Could this be an entropy problem again, as I discovered here:

https://groups.google.com/forum/#!topic/go-cd/BPQiOSNMT9I

thanks

@zuriar
Copy link

zuriar commented Jul 7, 2016

@tpbrown - awesome, those two commits have fixed the hanging server start. Much appreciated. Now have a singed ssl cert in the container ;)

@arvindsv
Copy link
Member

Also, @tpbrown has some thoughts about setting up an automated build using remote build triggers which should get us away from the restriction of a single repo with a single Dockerfile.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 14, 2016

Hmm. That's essentially what I did in my testing (with success), with the exception that I just used local folders (instead of docker volumes).

I'll run through with your scenarios and see what happens.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 14, 2016

One more bit -- this is using the JDK now, but I'll switch it over to the JRE. That'll slim things down.

@arvindsv
Copy link
Member

When I did:

GO_VERSION=16.5.0-3305 docker build -f Dockerfile.alpine-gocd-server --tag=alpine-gocd-server-16-5 .
GO_VERSION=16.6.0-3590 docker build -f Dockerfile.alpine-gocd-server --tag=alpine-gocd-server-16-6 .

I could see from the speed of the second build completing that it just used the cache. I checked the output and could see it was using the hard-coded ENV value. Finally I tried this and it worked:

GO_VERSION=junk-version docker build -f Dockerfile.alpine-gocd-server --tag=alpine-gocd-server-junk .

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 14, 2016

@arvindsv yup. I just switched it over to ARG and that's working.

Startup takes ~1min (2010 MBP, 8GB running Docker for Mac 1.12.0-rc4-beta19 -- but on a hybrid SSD/spinning disk)

Upgrade from 16.5 - 16.6 worked as expected. No data loss. Build didn't re-trigger.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 14, 2016

@arvindsv I'll hold off on the JRE switch. busybox.net is down and I can't pul the SSL helper for wget -- and I don't want to switch to an http download of GoCD.

@arvindsv
Copy link
Member

I'll hold off on the JRE switch. busybox.net is down and I can't pul the SSL helper for wget -- and I don't want to switch to an http download of GoCD.

@tpbrown: Alright.

Since I had the script ready, I went ahead and took a look at your ARG change. It looks good to me and I was able to run through the scenario I wanted to (it's below). It works really well! The agent upgraded itself as well. I decided to up the RAM allocation to Docker and I'm using 3GB now.

# Create a few named volumes, rather than creating a volume container.
docker volume create --name gocd-1-config
docker volume create --name gocd-1-artifacts
docker volume create --name gocd-1-logs

# Build a 16.5.0 and a 16.6.0 alpine-based image.
docker build --build-arg GO_VERSION=16.5.0-3305 -f Dockerfile.alpine-gocd-server --tag=alpine-gocd-server-16-5 .
docker build --build-arg GO_VERSION=16.6.0-3590 -f Dockerfile.alpine-gocd-server --tag=alpine-gocd-server-16-6 .

# Start 16.5 server (could have used volumes-from, if using a data volume)
docker run -tiP -v gocd-1-config:/config -v gocd-1-artifacts:/artifacts -v gocd-1-logs:/logs --name go-server-alpine alpine-gocd-server-16-5

# Start an agent
docker run -ti --link go-server-alpine:go-server gocd/gocd-agent

# Create a pipeline
# Let it finish

# Ctrl + C on the server.

# Start 16.6 server
docker run -tiP -v gocd-1-config:/config -v gocd-1-artifacts:/artifacts -v gocd-1-logs:/logs --name go-server-alpine alpine-gocd-server-16-6

# Expectation (and reality): The server comes up with the existing config (and pipeline information).

@arvindsv arvindsv merged commit 73056d6 into gocd:master Jul 14, 2016
@arvindsv
Copy link
Member

Thanks, @tpbrown! It's merged.

@zabil: What next? I've merged it since it was named differently anyway. It's your decision about making it the default image (my vote is for it, in case it helps). We need to change the pipeline in Snap to use this too.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 14, 2016

@arvindsv Here's what it'll look like with the JRE. Alpine 3.4 + openjdk8-jre-base. If we weren't using log4j we could use jre compact3 which drops another 40MB (?) off.

$ docker images|grep -i gocd
alpine-gocd-server-16-6-jre        latest              0bb5c9a45dd6        55 seconds ago      264.8 MB
alpine-gocd-server-16-6            latest              3e9c11789d78        43 minutes ago      321.2 MB
alpine-gocd-server-16-5            latest              5c2b720e66f5        About an hour ago   318 MB
gocd/gocd-agent                    latest              4c76efe63a8f        2 weeks ago         676.3 MB

@tpbrown tpbrown deleted the alpine branch July 14, 2016 20:21
@zabil
Copy link
Contributor

zabil commented Jul 15, 2016

We need to change the pipeline in Snap to use this too.

This docker file and docker command won't run on snap.
--build-args was introduced on docker 1.9, snap comes with docker 1.5 and that's why you see the erb's

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 15, 2016

That's easily changed, right?

On Jul 14, 2016, at 6:37 PM, Zabil Cheriya Maliackal [email protected] wrote:

We need to change the pipeline in Snap to use this too.

This docker file and docker command won't run on snap.
--build-args was introduced on docker 1.9, snap comes with docker 1.5 and that's why you see the erb's


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@ketan
Copy link
Member

ketan commented Jul 15, 2016

s/plasma/padma/ stupid autocorrect

On Fri, Jul 15, 2016, 8:11 AM Ketan Padegaonkar [email protected]
wrote:

Ask plasma to hook you up with Ubuntu. You'll get a newer kernel where you
can install docker from upstream.

On Fri, Jul 15, 2016, 7:07 AM Zabil Cheriya Maliackal <
[email protected]> wrote:

We need to change the pipeline in Snap to use this too.

This docker file and docker command won't run on snap.
--build-args was introduced on docker 1.9, snap comes with docker 1.5
and that's why you see the erb's


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#42 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAApZj3axc3pnGI1D4TeCO7vy8BzZEfoks5qVuRngaJpZM4JFmxv
.

@ketan
Copy link
Member

ketan commented Jul 15, 2016

Ask plasma to hook you up with Ubuntu. You'll get a newer kernel where you
can install docker from upstream.

On Fri, Jul 15, 2016, 7:07 AM Zabil Cheriya Maliackal <
[email protected]> wrote:

We need to change the pipeline in Snap to use this too.

This docker file and docker command won't run on snap.
--build-args was introduced on docker 1.9, snap comes with docker 1.5 and
that's why you see the erb's


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#42 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAApZj3axc3pnGI1D4TeCO7vy8BzZEfoks5qVuRngaJpZM4JFmxv
.

@zabil
Copy link
Contributor

zabil commented Jul 15, 2016

I had raised a ticket on snap earlier where they told me that can't be done.
Here's a snippet from support

Unfortunately, Snap has limitations that require a custom Docker install. For now, this also means that users won't be able to upgrade Docker themselves.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 15, 2016

@zabil re: --build-arg, does it ignore the ARG statement (as in, it'll run but you can't override) or does it error out?

if the former then we can combine ENV & ARG and it should work. I don't have 1.5 to test with :-( :

ARG GO_VERSION
ENV GO_VERSION=${GO_VERSION:-16.6.0-3590}

@arvindsv
Copy link
Member

We were talking about bringing it to an agent on build.go.cd instead. We should be able to. Let's see what happens early next week.

@FredrikWendt
Copy link
Contributor

+1 for staying outside Snap

@zabil
Copy link
Contributor

zabil commented Jul 17, 2016

@tpbrown

does it ignore the ARG statement

It errors out

We were talking about bringing it to an agent on build.go.cd instead

Tried this, not possible, our agents are on centos 6.7, docker versions greater than 1.5 only runs on centos 7 https://docs.docker.com/engine/installation/linux/centos/

@arvindsv
Copy link
Member

I'm sure we can gently ... convince @Junaidshah to help with that. :)

That's fine. I think we should explore automated dockerhub builds that @tpbrown already has working. If I find some time over the next few days, I'll try (I'm away Friday to Sunday this weekend, though). If not. maybe @zabil can take a look?

@zuriar
Copy link

zuriar commented Jul 20, 2016

Hi all

Is it me or does the base image (delitescere/jdk) not come with ssh installed? This means running go-cd-server off this image will not be possible to ssh a git repo. Should this be installed?

thanks
Hugh

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 20, 2016

@zuriar That's correct. It really is a minimal image.

There's always going to be a missing package someone wants (hello Mercurial support!), so I assume that people will use this as a base image and add whatever packages they desire.

FWIW - I just opened a PR #44 so that task is really trivial.

(side note: All that above rubbish is just my opinion. I'm not on the GoCD team. I'm just an annoyance. ;-))

@zuriar
Copy link

zuriar commented Jul 20, 2016

@tpbrown the problem is that the server appears to need ssh-client to check a git connection. I guess it is the agent which needs to actually use ssh to pull... would be useful including ssh on the main image, as it is relied upon in core functionality of the server?

@arvindsv
Copy link
Member

arvindsv commented Jul 20, 2016

@zuriar: That's not true. The core functionality of the server does not depend on SSH. The git command-line client does use ssh if you use the git protocol (or some others). You should be able to verify that GoCD server (and agent) will work with git without SSH by using the https way to access a repo.

For instance, to use a small repo: https://github.com/gocd-contrib/script-executor-task.git

You'll see that it does not need ssh client installed for that. However, if you want to use [email protected]:gocd-contrib/script-executor-task.git, then it'll need it.

@zuriar
Copy link

zuriar commented Jul 20, 2016

@arvindsv ok I take your point, but if the git sever only allows connections over ssh then it is kinda splitting hairs. I would still recommend adding ssh as a required dependency otherwise people will get very frustrated not being able to check their git connections in a manner they are used to (or required to). Eg, I am working against a git server which has a strict policy of only allowing ssh connections, not password/https.

@ketan
Copy link
Member

ketan commented Jul 20, 2016

+1 to adding the ssh cli :) Setting up ssh keys is already painful with GoCD, lets not add to it to save a few MBs.

@tpbrown
Copy link
Contributor Author

tpbrown commented Jul 20, 2016

Ok so it's:

  • add OpenSSH-client (~7MB)
  • provide a way to insert keys & known hosts

Anything else?

~Sent from my mobile device. Please pardon any oddities :-)

On Jul 20, 2016, at 10:14 AM, Ketan Padegaonkar [email protected] wrote:

+1 to adding the ssh cli :) Setting up ssh keys is already painful with GoCD, lets not add to it to save a few MBs.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

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

Successfully merging this pull request may close these issues.

7 participants