-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocker-container-for-a-simple-flask-app.html
220 lines (177 loc) · 12.4 KB
/
docker-container-for-a-simple-flask-app.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<!DOCTYPE html>
<html lang="english">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="HandheldFriendly" content="True" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="index, follow" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700,400italic' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="http://olipratt.co.uk/theme/stylesheet/style.min.css">
<link rel="stylesheet" type="text/css" href="http://olipratt.co.uk/theme/pygments/monokai.min.css">
<link rel="stylesheet" type="text/css" href="http://olipratt.co.uk/theme/font-awesome/css/font-awesome.min.css">
<link href="http://olipratt.co.uk/static/custom.css" rel="stylesheet">
<link href="http://olipratt.co.uk/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Oli Pratt's Blog Atom">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<!-- Chrome, Firefox OS and Opera -->
<meta name="theme-color" content="#282828">
<!-- Windows Phone -->
<meta name="msapplication-navbutton-color" content="#282828">
<!-- iOS Safari -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- Microsoft EDGE -->
<meta name="msapplication-TileColor" content="#282828">
<meta name="author" content="Oli Pratt" />
<meta name="description" content="Continuing the recent microservices trend, I tried to containerise a previous project, a small REST datastore - microstore. I’m not going to go into detail on what containers are (not least because I don’t think I could!) - but briefly they are a way to package up an app and it’s dependencies so they can be run in their own mini-environment. The best intro is just to follow the tutorial here. Creating the Container …" />
<meta name="keywords" content="Python, Flask, Container, Docker, microservice">
<meta property="og:site_name" content="Oli Pratt's Blog"/>
<meta property="og:title" content="Docker Container for a simple Flask App"/>
<meta property="og:description" content="Continuing the recent microservices trend, I tried to containerise a previous project, a small REST datastore - microstore. I’m not going to go into detail on what containers are (not least because I don’t think I could!) - but briefly they are a way to package up an app and it’s dependencies so they can be run in their own mini-environment. The best intro is just to follow the tutorial here. Creating the Container …"/>
<meta property="og:locale" content="en_GB"/>
<meta property="og:url" content="http://olipratt.co.uk/docker-container-for-a-simple-flask-app.html"/>
<meta property="og:type" content="article"/>
<meta property="article:published_time" content="2017-03-01 21:36:00+00:00"/>
<meta property="article:modified_time" content=""/>
<meta property="article:author" content="http://olipratt.co.uk/author/oli-pratt.html">
<meta property="article:section" content="Containers"/>
<meta property="article:tag" content="Python"/>
<meta property="article:tag" content="Flask"/>
<meta property="article:tag" content="Container"/>
<meta property="article:tag" content="Docker"/>
<meta property="article:tag" content="microservice"/>
<meta property="og:image" content="http://olipratt.co.uk/static/images/site_logo.png">
<title>Oli Pratt's Blog – Docker Container for a simple Flask App</title>
</head>
<body>
<aside>
<div>
<a href="http://olipratt.co.uk">
<img src="http://olipratt.co.uk/static/images/site_logo.png" alt="Oli Pratt" title="Oli Pratt">
</a>
<h1><a href="http://olipratt.co.uk">Oli Pratt</a></h1>
<p>Software Engineer</p>
<nav>
<ul class="list">
<li><a href="http://olipratt.co.uk/pages/about-me.html#about-me">About Me</a></li>
<li><a href="https://www.metaswitch.com/" target="_blank">Metaswitch</a></li>
</ul>
</nav>
<ul class="social">
<li><a class="sc-github" href="https://github.com/olipratt" target="_blank"><i class="fa fa-github"></i></a></li>
<li><a class="sc-linkedin" href="https://www.linkedin.com/in/olipratt/" target="_blank"><i class="fa fa-linkedin"></i></a></li>
<li><a class="sc-rss" href="/feeds/all.atom.xml" target="_blank"><i class="fa fa-rss"></i></a></li>
</ul>
</div>
</aside>
<main>
<nav>
<a href="http://olipratt.co.uk"> Home
</a>
<a href="/archives.html">Archives</a>
<a href="/categories.html">Categories</a>
<a href="/tags.html">Tags</a>
<a href="http://olipratt.co.uk/feeds/all.atom.xml"> Atom
</a>
</nav>
<article class="single">
<header>
<h1 id="docker-container-for-a-simple-flask-app">Docker Container for a simple Flask App</h1>
<p>
Posted on Wed 01 March 2017 in <a href="http://olipratt.co.uk/category/containers.html">Containers</a>
• 3 min read
</p>
</header>
<div>
<p>Continuing the recent microservices trend, I tried to containerise a previous project, a small REST datastore - <a href="http://olipratt.co.uk/python-rest-api-with-swaggerui.html">microstore</a>.</p>
<p>I’m not going to go into detail on what containers are (not least because I don’t think I could!) - but briefly they are a way to package up an app and it’s dependencies so they can be run in their own mini-environment. The best intro is just to follow the tutorial <a href="https://docs.docker.com/engine/getstarted/">here</a>.</p>
<h2 id="creating-the-container">Creating the Container</h2>
<p>I installed <a href="https://docs.docker.com/engine/installation/linux/centos/">Docker on CentOS</a>. It warns you not to just <code>yum install</code>, so instead I followed the <em>Install from a package</em> instructions - but note that you now have to always run docker commands with <code>sudo</code>.</p>
<p>Containerising an app was simple - basically <a href="https://runnable.com/docker/python/dockerize-your-flask-application">just follow this tutorial</a>.</p>
<p><a href="https://github.com/olipratt/microstore/blob/master/Dockerfile">Here’s</a> the <code>Dockerfile</code> I created following that - now in the microstore repo.</p>
<p>Note I had to set the app to listen on <code>0.0.0.0</code> because we are going to forward ports to outside the container, so need to listen on a public address inside the container.</p>
<p>So if you have docker installed, just:</p>
<ul>
<li>get a clone of the microstore repo,</li>
<li>build the container image with: <code>sudo docker build -t microstore:latest .</code></li>
<li>then run it with: <code>sudo docker run -p 5000:5000 microstore</code></li>
</ul>
<p>The <code>-p 5000:5000</code> binds port 5000 of the container to port 5000 on the host.
So now you can just go to <code>http://127.0.0.1:5000/</code> in your web browser and you should see the SwaggerUI running!</p>
<p>Some notes on running containers:</p>
<ul>
<li>If there’s a problem building/running the app, you can just run the same commands again after fixing the problem.</li>
<li>Add the <code>-d</code> option to run the container in the background.</li>
<li>Note <code>sudo docker ps</code> shows what containerised apps are running.</li>
</ul>
<h2 id="shipping-an-image">Shipping an Image</h2>
<p>You can now create the final container ready to ship with <code>sudo docker save microstore > microstore.tar</code>. This one was about 300MB when I created it.</p>
<p>Later/elsewhere you can reload it with <code>sudo docker load < microstore.tar</code>.</p>
<h2 id="composing-multiple-containers">Composing Multiple Containers</h2>
<p>Now I’d got one running, I wanted to see how you’d ship several microservices given they would need to contact each other over IP somehow. Turns out that’s simple too using <code>docker-compose</code>.</p>
<p>Again, not going into detail on this as it’s all online.</p>
<ul>
<li>There’s a good tutorial <a href="https://docs.docker.com/compose/gettingstarted/">here</a>.</li>
<li>You may need to specify a <a href="https://docs.docker.com/compose/startup-order/">startup order</a> so that a service is created before another tries to connect to it.</li>
<li>Networking between services is also simple - basically <a href="https://docs.docker.com/compose/networking/">access the name of a service in the compose file as a hostname</a>.</li>
</ul>
<p>I set up my little card deck service with a <a href="https://github.com/olipratt/microcarddeck/blob/master/Dockerfile">Dockerfile</a> and <a href="https://github.com/olipratt/microcarddeck/blob/master/docker-compose.yml">compose file</a> to run it and the microstore together. If you built the microstore container above, then by just running <code>sudo docker-compose up</code> in the card deck repo it will build the second image and then run them both together - magic!</p>
<p><em>One note - I was confused that <code>sudo docker-compose up</code> didn’t rebuild the image after fixing a bug in the <code>Dockerfile</code> but, as per <a href="https://github.com/docker/compose/issues/1487">here</a>, you need to run <code>sudo docker-compose build</code> to force it to rebuild - <code>up</code> won’t ever rebuild.</em></p>
<h2 id="tidying-up">Tidying up</h2>
<p>Docker seems to leave images that you create as you iterate lying around, and you have to do a bit of manual cleanup at the end. As noted in <a href="https://docs.docker.com/compose/gettingstarted/">here</a> you can clear up composed containers with <code>sudo docker-compose down</code>. You can then <a href="https://docs.docker.com/engine/reference/commandline/image_prune/">prune</a> and <a href="https://docs.docker.com/engine/reference/commandline/rm/#/remove-all-stopped-containers">remove unused images</a>.</p>
<hr>
<p>That was really simple and Docker seems like a great way for running at least simple apps in a controlled environment. What’s been your experience with Docker, if any?</p>
</div>
<div class="tag-cloud">
<p>
<a href="http://olipratt.co.uk/tag/python.html">Python</a>
<a href="http://olipratt.co.uk/tag/flask.html">Flask</a>
<a href="http://olipratt.co.uk/tag/container.html">Container</a>
<a href="http://olipratt.co.uk/tag/docker.html">Docker</a>
<a href="http://olipratt.co.uk/tag/microservice.html">microservice</a>
</p>
</div>
<div class="neighbors">
<a class="btn float-left" href="http://olipratt.co.uk/python-microservice-logging.html" title="Python Microservice Logging">
<i class="fa fa-angle-left"></i> Previous Post
</a>
<a class="btn float-right" href="http://olipratt.co.uk/building-vs-code-extensions-in-docker-containers.html" title="Building VS Code Extensions in Docker Containers">
Next Post
<i class="fa fa-angle-right"></i>
</a>
</div>
</article>
<footer>
<p>© Oli Pratt </p>
<p> Powered by <a href="http://getpelican.com" target="_blank">Pelican</a> - <a href="https://github.com/alexandrevicenzi/flex" target="_blank">Flex</a> theme by <a href="http://alexandrevicenzi.com" target="_blank">Alexandre Vicenzi</a>
</p> </footer>
</main>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "BlogPosting",
"name": "Docker Container for a simple Flask App",
"headline": "Docker Container for a simple Flask App",
"datePublished": "2017-03-01 21:36:00+00:00",
"dateModified": "2017-03-01 21:36:00+00:00",
"author": {
"@type": "Person",
"name": "Oli Pratt"
},
"publisher": {
"@type": "Organization",
"name": "Oli Pratt",
"logo": {
"@type": "ImageObject",
"url": "http://olipratt.co.uk/static/images/site_logo.png"
}
},
"image": "http://olipratt.co.uk/static/images/site_logo.png",
"mainEntityOfPage": "http://olipratt.co.uk/docker-container-for-a-simple-flask-app.html",
"url": "http://olipratt.co.uk/docker-container-for-a-simple-flask-app.html",
"description": "Continuing the recent microservices trend, I tried to containerise a previous project, a small REST datastore - microstore. I’m not going to go into detail on what containers are (not least because I don’t think I could!) - but briefly they are a way to package up an app and it’s dependencies so they can be run in their own mini-environment. The best intro is just to follow the tutorial here. Creating the Container …"
}
</script>
</body>
</html>