Skip to content

Add new -overlay option to overlay files prior to templatizing #31

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ CMD dockerize -template /etc/nginx/nginx.tmpl:/etc/nginx/nginx.conf -stdout /var

### Command-line Options

You can specify multiple templates by passing using `-template` multiple times:
You can specify multiple templates by passing `-template` multiple times:

```
$ dockerize -template template1.tmpl:file1.cfg -template template2.tmpl:file3
$ dockerize -template template1.tmpl:file1.cfg -template template2.tmpl:file2

```

Expand All @@ -68,6 +68,15 @@ $ dockerize -template template1.tmpl
```


You can overlay files onto the container at runtime by passing `-overlay` multiple times. The argument uses a form similar to the `--volume` option of the `docker run` command: `source:dest`. Overlays are applied recursively onto the destination in a similar manner to `cp -rv`. If multiple overlays are specified, they are applied in the order in which they were listed on the command line.

Overlays are used to replace entire sets of files with alternative content, whereas templates allow environment substitutions into a single file. The example below assumes that /tmp/overlays has already been COPY'd into the image by the Dockerfile.

```
$ dockerize -overlay "/tmp/overlays/_common/html:/usr/share/nginx/" \
-overlay "/tmp/overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/"
```

You can tail multiple files to `STDOUT` and `STDERR` by passing the options multiple times.

```
Expand Down
47 changes: 32 additions & 15 deletions dockerize.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"os"
"os/exec"
"strings"
"sync"
"time"
Expand All @@ -18,18 +19,6 @@ import (
type sliceVar []string
type hostFlagsVar []string

type Context struct {
}

func (c *Context) Env() map[string]string {
env := make(map[string]string)
for _, i := range os.Environ() {
sep := strings.Index(i, "=")
env[i[0:sep]] = i[sep+1:]
}
return env
}

var (
buildVersion string
version bool
Expand All @@ -39,6 +28,7 @@ var (
templatesFlag sliceVar
stdoutTailFlag sliceVar
stderrTailFlag sliceVar
overlaysFlag sliceVar
delimsFlag string
Copy link
Author

Choose a reason for hiding this comment

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

I found this confusing -- I thought it was somehow related to golang.org/x/net/context.Context and the ctx variable. So I renamed it to EnvContext and moved it into templates.go, which is the only place its used

delims []string
waitFlag hostFlagsVar
Expand Down Expand Up @@ -70,6 +60,10 @@ func (s *sliceVar) String() string {
func waitForDependencies() {
dependencyChan := make(chan struct{})

if waitFlag == nil {
return
}

go func() {
for _, host := range waitFlag {
log.Println("Waiting for host:", host)
Expand Down Expand Up @@ -104,7 +98,7 @@ func waitForDependencies() {
}
}()
default:
log.Fatalf("invalid host protocol provided: %s. supported protocols are: tcp, tcp4, tcp6 and http", u.Scheme)
log.Fatalf("invalid host protocol provided: %s. supported protocols are: tcp, tcp4, tcp6, http and https", u.Scheme)
}
}
wg.Wait()
Expand Down Expand Up @@ -139,7 +133,9 @@ Arguments:
and /var/log/nginx/error.log, waiting for a website to become available on port 8000 and start nginx.`)
println(`
dockerize -template nginx.tmpl:/etc/nginx/nginx.conf \
-stdout /var/log/nginx/access.log \
-overlay overlays/_common/html:/usr/share/nginx/ \
-overlay overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/ \`)
println(` -stdout /var/log/nginx/access.log \
-stderr /var/log/nginx/error.log \
-wait tcp://web:8000 nginx
`)
Expand All @@ -152,6 +148,7 @@ func main() {
flag.BoolVar(&version, "version", false, "show version")
flag.BoolVar(&poll, "poll", false, "enable polling")
flag.Var(&templatesFlag, "template", "Template (/template:/dest). Can be passed multiple times")
flag.Var(&overlaysFlag, "overlay", "overlay (/src:/dest). Can be passed multiple times")
flag.Var(&stdoutTailFlag, "stdout", "Tails a file to stdout. Can be passed multiple times")
flag.Var(&stderrTailFlag, "stderr", "Tails a file to stderr. Can be passed multiple times")
flag.StringVar(&delimsFlag, "delims", "", `template tag delimiters. default "{{":"}}" `)
Expand All @@ -177,14 +174,34 @@ func main() {
log.Fatalf("bad delimiters argument: %s. expected \"left:right\"", delimsFlag)
}
}

// Overlay files from src --> dst
for _, o := range overlaysFlag {
if strings.Contains(o, ":") {
parts := strings.Split(o, ":")
if len(parts) != 2 {
log.Fatalf("bad overlay argument: '%s'. expected \"/src:/dest\"", o)
}
src, dest := string_template_eval(parts[0]), string_template_eval(parts[1])

log.Printf("overlaying %s --> %s", src, dest)

cmd := exec.Command("cp", "-rv", src, dest)
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
}

for _, t := range templatesFlag {
template, dest := t, ""
if strings.Contains(t, ":") {
parts := strings.Split(t, ":")
if len(parts) != 2 {
log.Fatalf("bad template argument: %s. expected \"/template:/dest\"", t)
}
template, dest = parts[0], parts[1]
template, dest = string_template_eval(parts[0]), string_template_eval(parts[1])
}
generateFile(template, dest)
}
Expand Down
1 change: 1 addition & 0 deletions examples/nginx/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.gz
37 changes: 24 additions & 13 deletions examples/nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
FROM ubuntu:14.04
FROM nginx:1.9
MAINTAINER Jason Wilder [email protected]

# Install Nginx.
RUN echo "deb http://ppa.launchpad.net/nginx/stable/ubuntu trusty main" > /etc/apt/sources.list.d/nginx-stable-trusty.list
RUN echo "deb-src http://ppa.launchpad.net/nginx/stable/ubuntu trusty main" >> /etc/apt/sources.list.d/nginx-stable-trusty.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
RUN apt-get update
RUN apt-get install -y wget nginx
# RUN wget https://github.com/markriggins/dockerize/releases/download/v0.2.0/dockerize-linux-amd64-v0.0.4.tar.gz
# RUN tar -C /usr/local/bin -xvzf dockerize-linux-amd64-v0.2.0.tar.gz

RUN wget https://github.com/jwilder/dockerize/releases/download/v0.0.4/dockerize-linux-amd64-v0.0.4.tar.gz
RUN tar -C /usr/local/bin -xvzf dockerize-linux-amd64-v0.0.4.tar.gz
COPY .dockerize_linux_amd64.tar.gz /tmp/
RUN cd /usr/local/bin && \
tar -xzv --strip-components=1 -f /tmp/.d*.gz dockerize_linux_amd64/dockerize && \
rm /tmp/.d*.gz

RUN echo "daemon off;" >> /etc/nginx/nginx.conf

ADD default.tmpl /etc/nginx/sites-available/default.tmpl
COPY default.tmpl /etc/nginx/sites-available/default.tmpl
COPY overlays /tmp/overlays

EXPOSE 80

CMD ["dockerize", "-template", "/etc/nginx/sites-available/default.tmpl:/etc/nginx/sites-available/default", "-stdout", "/var/log/nginx/access.log", "-stderr", "/var/log/nginx/error.log", "nginx"]
ENV DEPLOYMENT_ENV=staging

# These options do not work well on virtualbox osx -- it pegs one CPU
# "-poll", \
# "-stdout", "/var/log/nginx/access.log", \
# "-stderr", "/var/log/nginx/error.log", \

CMD [ "dockerize", \
"-template", "/etc/nginx/sites-available/default.tmpl:/etc/nginx/sites-available/default", \
"-overlay", "/tmp/overlays/_common/html:/usr/share/nginx/", \
"-overlay", "/tmp/overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/", \
"-poll", \
"-stdout", "/var/log/nginx/access.log", \
"-stderr", "/var/log/nginx/error.log", \
"--", "nginx", "-g", "daemon off;"]
18 changes: 18 additions & 0 deletions examples/nginx/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.PHONY : build run-staging run-prod

build:
cd ../..; goxc -os linux -arch amd64
cp -f $(shell bash -xc 'find $(GOPATH)/bin -name dockerize_linux_amd64.tar.gz| head -1') .dockerize_linux_amd64.tar.gz
docker build -t dockerized-nginx .
rm .dockerize_linux_amd64.tar.gz


run-staging:
docker rm -f dockerized-nginx 2>/dev/null || true
docker run -d -p 80:80 -e DEPLOYMENT_ENV=staging --name dockerized-nginx dockerized-nginx
open http://$(shell docker-machine ip $(shell docker-machine active))/robots.txt

run-prod:
docker rm -f dockerized-nginx 2>/dev/null || true
docker run -d -p 80:80 -e DEPLOYMENT_ENV=prod --name dockerized-nginx dockerized-nginx
open http://$(shell docker-machine ip $(shell docker-machine active))/robots.txt
5 changes: 5 additions & 0 deletions examples/nginx/overlays/_common/html/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
# Common robots.txt file
#
User-agent: *
Disallow: /
5 changes: 5 additions & 0 deletions examples/nginx/overlays/prod/html/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
# Prod robots.txt file
#
User-agent: *
Allow: /
39 changes: 38 additions & 1 deletion template.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"fmt"
"log"
"net/url"
Expand All @@ -12,6 +13,18 @@ import (
"text/template"
)

type EnvContext struct {
}

func (c *EnvContext) Env() map[string]string {
env := make(map[string]string)
for _, i := range os.Environ() {
sep := strings.Index(i, "=")
env[i[0:sep]] = i[sep+1:]
}
return env
}

func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
Expand Down Expand Up @@ -68,6 +81,30 @@ func add(arg1, arg2 int) int {
return arg1 + arg2
}

//
// Execute the string_template under the EnvContext, and
// return the result as a string
//
func string_template_eval(string_template string) string {
var result bytes.Buffer
t := template.New("String Template")

t, err := t.Parse(string_template)
if err != nil {
log.Fatalf("unable to parse template: %s", err)
}

err = t.Execute(&result, &EnvContext{})
if err != nil {
log.Fatalf("template error: %s\n", err)
}

return result.String()
}

//
// Execute the template at templatePath under the EnvContext and write it to destPath
//
func generateFile(templatePath, destPath string) bool {
tmpl := template.New(filepath.Base(templatePath)).Funcs(template.FuncMap{
"contains": contains,
Expand Down Expand Up @@ -97,7 +134,7 @@ func generateFile(templatePath, destPath string) bool {
defer dest.Close()
}

err = tmpl.ExecuteTemplate(dest, filepath.Base(templatePath), &Context{})
err = tmpl.ExecuteTemplate(dest, filepath.Base(templatePath), &EnvContext{})
if err != nil {
log.Fatalf("template error: %s\n", err)
}
Expand Down