Skip to content

Commit bcc08d3

Browse files
committed
Add new -overlay option to overlay files prior to templatizing
- overlays files onto the container at run-time, allowing for entire directory trees of files to be dropped into a container based on ENV settings `dockerize -overlay "/tmp/overlays/_common/html:/usr/share/nginx/" \ -overlay "/tmp/overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/" ...` Small improvements: - rename Context to EnvContext and move it into template.go, which is the only place it is used. - Add early exit to waitForDependencies() if waitFlag is nil - string_template_eval utility function added - apply string_template_eval to -template args so users use ENV vars to select the desired template at run-time like this: `dockerize -template '/etc/nginx/sites-available/{{ .Env FLAVOR }}.default.tmpl:/etc/nginx/sites-available/default' Nginx Example improvements - FROM nginx:1.9 is MUCH faster than compiling your own nginx - Add a Makefile for examples/nginx - Install the locally built image of "dockerize" into nginx, this greatly simplifies testing
1 parent 246bc5e commit bcc08d3

8 files changed

Lines changed: 134 additions & 31 deletions

File tree

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ CMD dockerize -template /etc/nginx/nginx.tmpl:/etc/nginx/nginx.conf -stdout /var
5353

5454
### Command-line Options
5555

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

5858
```
59-
$ dockerize -template template1.tmpl:file1.cfg -template template2.tmpl:file3
59+
$ dockerize -template template1.tmpl:file1.cfg -template template2.tmpl:file2
6060
6161
```
6262

@@ -68,6 +68,15 @@ $ dockerize -template template1.tmpl
6868
```
6969

7070

71+
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.
72+
73+
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.
74+
75+
```
76+
$ dockerize -overlay "/tmp/overlays/_common/html:/usr/share/nginx/" \
77+
-overlay "/tmp/overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/"
78+
```
79+
7180
You can tail multiple files to `STDOUT` and `STDERR` by passing the options multiple times.
7281

7382
```

dockerize.go

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"net/url"
1010
"os"
11+
"os/exec"
1112
"strings"
1213
"sync"
1314
"time"
@@ -18,18 +19,6 @@ import (
1819
type sliceVar []string
1920
type hostFlagsVar []string
2021

21-
type Context struct {
22-
}
23-
24-
func (c *Context) Env() map[string]string {
25-
env := make(map[string]string)
26-
for _, i := range os.Environ() {
27-
sep := strings.Index(i, "=")
28-
env[i[0:sep]] = i[sep+1:]
29-
}
30-
return env
31-
}
32-
3322
var (
3423
buildVersion string
3524
version bool
@@ -39,6 +28,7 @@ var (
3928
templatesFlag sliceVar
4029
stdoutTailFlag sliceVar
4130
stderrTailFlag sliceVar
31+
overlaysFlag sliceVar
4232
delimsFlag string
4333
delims []string
4434
waitFlag hostFlagsVar
@@ -70,6 +60,10 @@ func (s *sliceVar) String() string {
7060
func waitForDependencies() {
7161
dependencyChan := make(chan struct{})
7262

63+
if waitFlag == nil {
64+
return
65+
}
66+
7367
go func() {
7468
for _, host := range waitFlag {
7569
log.Println("Waiting for host:", host)
@@ -104,7 +98,7 @@ func waitForDependencies() {
10498
}
10599
}()
106100
default:
107-
log.Fatalf("invalid host protocol provided: %s. supported protocols are: tcp, tcp4, tcp6 and http", u.Scheme)
101+
log.Fatalf("invalid host protocol provided: %s. supported protocols are: tcp, tcp4, tcp6, http and https", u.Scheme)
108102
}
109103
}
110104
wg.Wait()
@@ -139,7 +133,9 @@ Arguments:
139133
and /var/log/nginx/error.log, waiting for a website to become available on port 8000 and start nginx.`)
140134
println(`
141135
dockerize -template nginx.tmpl:/etc/nginx/nginx.conf \
142-
-stdout /var/log/nginx/access.log \
136+
-overlay overlays/_common/html:/usr/share/nginx/ \
137+
-overlay overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/ \`)
138+
println(` -stdout /var/log/nginx/access.log \
143139
-stderr /var/log/nginx/error.log \
144140
-wait tcp://web:8000 nginx
145141
`)
@@ -152,6 +148,7 @@ func main() {
152148
flag.BoolVar(&version, "version", false, "show version")
153149
flag.BoolVar(&poll, "poll", false, "enable polling")
154150
flag.Var(&templatesFlag, "template", "Template (/template:/dest). Can be passed multiple times")
151+
flag.Var(&overlaysFlag, "overlay", "overlay (/src:/dest). Can be passed multiple times")
155152
flag.Var(&stdoutTailFlag, "stdout", "Tails a file to stdout. Can be passed multiple times")
156153
flag.Var(&stderrTailFlag, "stderr", "Tails a file to stderr. Can be passed multiple times")
157154
flag.StringVar(&delimsFlag, "delims", "", `template tag delimiters. default "{{":"}}" `)
@@ -177,14 +174,34 @@ func main() {
177174
log.Fatalf("bad delimiters argument: %s. expected \"left:right\"", delimsFlag)
178175
}
179176
}
177+
178+
// Overlay files from src --> dst
179+
for _, o := range overlaysFlag {
180+
if strings.Contains(o, ":") {
181+
parts := strings.Split(o, ":")
182+
if len(parts) != 2 {
183+
log.Fatalf("bad overlay argument: '%s'. expected \"/src:/dest\"", o)
184+
}
185+
src, dest := string_template_eval(parts[0]), string_template_eval(parts[1])
186+
187+
log.Printf("overlaying %s --> %s", src, dest)
188+
189+
cmd := exec.Command("cp", "-rv", src, dest)
190+
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
191+
if err := cmd.Run(); err != nil {
192+
log.Fatal(err)
193+
}
194+
}
195+
}
196+
180197
for _, t := range templatesFlag {
181198
template, dest := t, ""
182199
if strings.Contains(t, ":") {
183200
parts := strings.Split(t, ":")
184201
if len(parts) != 2 {
185202
log.Fatalf("bad template argument: %s. expected \"/template:/dest\"", t)
186203
}
187-
template, dest = parts[0], parts[1]
204+
template, dest = string_template_eval(parts[0]), string_template_eval(parts[1])
188205
}
189206
generateFile(template, dest)
190207
}

examples/nginx/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.gz

examples/nginx/Dockerfile

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
1-
FROM ubuntu:14.04
1+
FROM nginx:1.9
22
MAINTAINER Jason Wilder mail@jasonwilder.com
33

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

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

14-
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
15-
16-
ADD default.tmpl /etc/nginx/sites-available/default.tmpl
12+
COPY default.tmpl /etc/nginx/sites-available/default.tmpl
13+
COPY overlays /tmp/overlays
1714

1815
EXPOSE 80
1916

20-
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"]
17+
ENV DEPLOYMENT_ENV=staging
18+
19+
# These options do not work well on virtualbox osx -- it pegs one CPU
20+
# "-poll", \
21+
# "-stdout", "/var/log/nginx/access.log", \
22+
# "-stderr", "/var/log/nginx/error.log", \
23+
24+
CMD [ "dockerize", \
25+
"-template", "/etc/nginx/sites-available/default.tmpl:/etc/nginx/sites-available/default", \
26+
"-overlay", "/tmp/overlays/_common/html:/usr/share/nginx/", \
27+
"-overlay", "/tmp/overlays/{{ .Env.DEPLOYMENT_ENV }}/html:/usr/share/nginx/", \
28+
"-poll", \
29+
"-stdout", "/var/log/nginx/access.log", \
30+
"-stderr", "/var/log/nginx/error.log", \
31+
"--", "nginx", "-g", "daemon off;"]

examples/nginx/Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.PHONY : build run-staging run-prod
2+
3+
build:
4+
cd ../..; goxc -os linux -arch amd64
5+
cp -f $(shell bash -xc 'find $(GOPATH)/bin -name dockerize_linux_amd64.tar.gz| head -1') .dockerize_linux_amd64.tar.gz
6+
docker build -t dockerized-nginx .
7+
rm .dockerize_linux_amd64.tar.gz
8+
9+
10+
run-staging:
11+
docker rm -f dockerized-nginx 2>/dev/null || true
12+
docker run -d -p 80:80 -e DEPLOYMENT_ENV=staging --name dockerized-nginx dockerized-nginx
13+
open http://$(shell docker-machine ip $(shell docker-machine active))/robots.txt
14+
15+
run-prod:
16+
docker rm -f dockerized-nginx 2>/dev/null || true
17+
docker run -d -p 80:80 -e DEPLOYMENT_ENV=prod --name dockerized-nginx dockerized-nginx
18+
open http://$(shell docker-machine ip $(shell docker-machine active))/robots.txt
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#
2+
# Common robots.txt file
3+
#
4+
User-agent: *
5+
Disallow: /
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#
2+
# Prod robots.txt file
3+
#
4+
User-agent: *
5+
Allow: /

template.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"bytes"
45
"fmt"
56
"log"
67
"net/url"
@@ -12,6 +13,18 @@ import (
1213
"text/template"
1314
)
1415

16+
type EnvContext struct {
17+
}
18+
19+
func (c *EnvContext) Env() map[string]string {
20+
env := make(map[string]string)
21+
for _, i := range os.Environ() {
22+
sep := strings.Index(i, "=")
23+
env[i[0:sep]] = i[sep+1:]
24+
}
25+
return env
26+
}
27+
1528
func exists(path string) (bool, error) {
1629
_, err := os.Stat(path)
1730
if err == nil {
@@ -68,6 +81,30 @@ func add(arg1, arg2 int) int {
6881
return arg1 + arg2
6982
}
7083

84+
//
85+
// Execute the string_template under the EnvContext, and
86+
// return the result as a string
87+
//
88+
func string_template_eval(string_template string) string {
89+
var result bytes.Buffer
90+
t := template.New("String Template")
91+
92+
t, err := t.Parse(string_template)
93+
if err != nil {
94+
log.Fatalf("unable to parse template: %s", err)
95+
}
96+
97+
err = t.Execute(&result, &EnvContext{})
98+
if err != nil {
99+
log.Fatalf("template error: %s\n", err)
100+
}
101+
102+
return result.String()
103+
}
104+
105+
//
106+
// Execute the template at templatePath under the EnvContext and write it to destPath
107+
//
71108
func generateFile(templatePath, destPath string) bool {
72109
tmpl := template.New(filepath.Base(templatePath)).Funcs(template.FuncMap{
73110
"contains": contains,
@@ -97,7 +134,7 @@ func generateFile(templatePath, destPath string) bool {
97134
defer dest.Close()
98135
}
99136

100-
err = tmpl.ExecuteTemplate(dest, filepath.Base(templatePath), &Context{})
137+
err = tmpl.ExecuteTemplate(dest, filepath.Base(templatePath), &EnvContext{})
101138
if err != nil {
102139
log.Fatalf("template error: %s\n", err)
103140
}

0 commit comments

Comments
 (0)