1 | Heroku CLI Docker Plugin
|
2 |
|
3 | # Set up boot2docker
|
4 |
|
5 | Install [boot2docker](http://boot2docker.io/) and make sure it works in your shell:
|
6 |
|
7 | ```
|
8 | docker ps
|
9 | ```
|
10 |
|
11 | (should run without errors)
|
12 |
|
13 | # Install the plugin
|
14 |
|
15 | ```
|
16 | heroku plugins:install heroku-docker
|
17 | ```
|
18 |
|
19 | # Create a local development environment
|
20 |
|
21 | ```
|
22 | mkdir myproject
|
23 | cd myproject
|
24 | heroku docker:create --template node
|
25 | ```
|
26 |
|
27 | `docker:create` creates a Dockerfile and uses that Dockerfile to build
|
28 | an image for local development, so you can run things like `npm install`.
|
29 | It performs checks in this order:
|
30 |
|
31 | 1. Is a template explicitly provided like `--template node`? If so, use that one.
|
32 | 2. Does a Dockerfile already exist? If so, leave the Dockerfile and just update the image.
|
33 | 3. Do any of our supported platforms detect files like `package.json`? Use what was detected.
|
34 |
|
35 | You now have a Dockerfile:
|
36 |
|
37 | ```
|
38 | cat Dockerfile
|
39 | ```
|
40 |
|
41 | Ensure the environment works:
|
42 |
|
43 | ```
|
44 | heroku docker:run node --version
|
45 | ```
|
46 |
|
47 | You can also operate within a shell:
|
48 |
|
49 | ```
|
50 | heroku docker:run bash
|
51 | ```
|
52 |
|
53 | # Start with hello world
|
54 |
|
55 | Echo out a simple JS file:
|
56 |
|
57 | ```
|
58 | echo 'console.log("Hello, world!");' > hello.js
|
59 | ```
|
60 |
|
61 | Now run it in your development container:
|
62 |
|
63 | ```
|
64 | heroku docker:run node hello.js
|
65 | ```
|
66 |
|
67 | # Upgrade to an actual server
|
68 |
|
69 | Create a package.json with `npm init` (keep all default settings):
|
70 |
|
71 | ```
|
72 | heroku docker:run npm init --yes
|
73 | ```
|
74 |
|
75 | I'll bet you expected `--yes` to just use defaults for everything and not
|
76 | prompt you for an author. Well you clearly haven't been using node for very long!
|
77 | We JavaScripters are masters of the ruse.
|
78 | This isn't just another nambly-pambly environment that follows conventions and
|
79 | does what you tell it to, oh no. We bring *excitement* to the command line!
|
80 |
|
81 | (Just leave author blank, or whatever. It doesn't matter)
|
82 |
|
83 | Install express:
|
84 |
|
85 | ```
|
86 | heroku docker:run npm install --save express
|
87 | ```
|
88 |
|
89 | Now create server.js:
|
90 |
|
91 | ```js
|
92 | var express = require('express');
|
93 | var PORT = process.env.PORT || 3000;
|
94 |
|
95 | express()
|
96 | .use(sayHi)
|
97 | .listen(PORT, onListen);
|
98 |
|
99 | function onListen(err) {
|
100 | console.log('Listening on', PORT);
|
101 | }
|
102 |
|
103 | function sayHi(req, res, next) {
|
104 | res.send('Hello, world!');
|
105 | }
|
106 | ```
|
107 |
|
108 | # Simulate Heroku, locally
|
109 |
|
110 | ```
|
111 | heroku docker:start
|
112 | ```
|
113 |
|
114 | Now check it out! While the server is running, open a new terminal
|
115 | and ensure that it has a correct `$DOCKER_HOST`:
|
116 |
|
117 | ```
|
118 | docker ps
|
119 | ```
|
120 |
|
121 | You should see your running container:
|
122 |
|
123 | ```
|
124 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
125 | b556b7a29c3e heroku-docker-2e793bb0-deed-11e4-8006-8d1a6e069a60:latest "npm start" 12 seconds ago Up 11 seconds 0.0.0.0:3000->3000/tcp jovial_thompson
|
126 | ```
|
127 |
|
128 | Then open your app in a browser:
|
129 |
|
130 | ```
|
131 | heroku docker:open
|
132 | ```
|
133 |
|
134 | # Customize your stack
|
135 |
|
136 | Node has a nice 'gm' module that lets you easily manipulate graphics.
|
137 | Let's augment server.js to generate custom pngs:
|
138 |
|
139 | ```
|
140 | heroku docker:run npm install --save gm
|
141 | ```
|
142 |
|
143 | ```js
|
144 | var express = require('express');
|
145 | var gm = require('gm');
|
146 | var path = require('path');
|
147 |
|
148 | var PORT = process.env.PORT || 3000;
|
149 |
|
150 | express()
|
151 | .use(express.static(__dirname))
|
152 | .use(createImage)
|
153 | .listen(PORT, onListen);
|
154 |
|
155 | function onListen(err) {
|
156 | console.log('Listening on', PORT);
|
157 | }
|
158 |
|
159 | function createImage(req, res, next) {
|
160 | var file = path.join(__dirname, 'img.png');
|
161 | var text = req.query.text || 'hello, world!';
|
162 | gm(525, 110, "#00ff55aa")
|
163 | .fontSize(68)
|
164 | .stroke("#efe", 2)
|
165 | .fill("#555")
|
166 | .drawText(20, 72, text)
|
167 | .write(file, function(err){
|
168 | if (err) throw err;
|
169 | res.send('<html><img src="/img.png"></html>');
|
170 | });
|
171 | }
|
172 | ```
|
173 |
|
174 | Now try it:
|
175 |
|
176 | ```
|
177 | heroku docker:start
|
178 | ```
|
179 |
|
180 | Oh yeah - Heroku's cedar-14 stack doesn't ship with GraphicsMagick!
|
181 | Open up your Dockerfile, and add this directly above the `WORKDIR /app/src` line:
|
182 |
|
183 | ```
|
184 | RUN curl -s http://78.108.103.11/MIRROR/ftp/GraphicsMagick/1.3/GraphicsMagick-1.3.21.tar.gz | tar xvz -C /tmp
|
185 | WORKDIR /tmp/GraphicsMagick-1.3.21
|
186 | RUN ./configure --disable-shared --disable-installed
|
187 | RUN make DESTDIR=/app install
|
188 | RUN echo "export PATH=\"/app/usr/local/bin:\$PATH\"" >> /app/.profile.d/nodejs.sh
|
189 | ENV PATH /app/usr/local/bin:$PATH
|
190 | ```
|
191 |
|
192 | Now, build a new development image and start your server:
|
193 |
|
194 | ```
|
195 | heroku docker:create
|
196 | heroku docker:start
|
197 | ```
|
198 |
|
199 | Now, the `gm` binary will be bundled with your app's slug.
|
200 | One neat thing to note here is that it's been compiled for ubuntu,
|
201 | so it will work on Heroku even if you're developing on another platform (like OSX).
|
202 |
|
203 | Test it out to see your new graphics-capable server in action:
|
204 |
|
205 | ```
|
206 | heroku docker:open
|
207 | ```
|
208 |
|
209 | Add a querystring like ?text=Node.js to dynamically create new images.
|
210 |
|
211 | # Release your app to Heroku
|
212 |
|
213 | ```
|
214 | git init
|
215 | heroku create
|
216 | heroku docker:release
|
217 | heroku open
|
218 | ```
|