Go Web Server and Docker: Trying to establish a workflow

agolangf · · 1379 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m working on a toy blog site in order to try to learn how to use Go and Docker together. This blog site is just for myself and not some big company product, so I don&#39;t <em>think</em> I need big words like &#34;Consul&#34;, &#34;Heroku&#34;, &#34;Puppet&#34;, &#34;Vagrant&#34;, etc. I don&#39;t even really know what those things do, I&#39;m still in school. :)</p> <p>Okay. Here&#39;s what I got so far.</p> <ul> <li>1 data-only container</li> <li>1 postgres container</li> <li>1 go container (built using onbuild trigger)</li> <li>1 nginx container (using as reverse proxy)</li> </ul> <p>These are the commands I used to set that up.</p> <pre><code># create postgres data container docker create -v /var/lib/postgresql/data --name pgdata postgres /bin/true # create Postgres container docker run --volumes-from pgdata -P --name pg1 -e POSTGRES_PASSWORD=mypass -d postgres # create go container; link to postgres container docker run -P --name goapp --link pg1:db -d appimg # create nginx container; link to go container docker run -p 80:80 -p 443:443 --name webproxy -v `pwd`/nginx.conf:/etc/nginx/nginx.conf:ro --link goapp:app -d nginx </code></pre> <p>This gets my blog site running. Fine. Great. Except: <strong>How do I modify and recompile my project now?</strong></p> <h3>Possible Solution 1</h3> <p>I tried mounting my Go directory as a volume with the <code>-v</code> flag. That does allow me to edit the code, however I can&#39;t execute the changes. I tried using <code>docker exec -it myapp /bin/bash</code> to run <code>go build</code> inside of my container, but I can&#39;t execute it because my project&#39;s project port is already in use.</p> <h3>Possible Solution 2</h3> <p>The other thing I tried was to <code>docker build -t myapp .</code> every time I make any changes to my code. This is awful though because I have to tear everything down and build it back up each time I make any changes. It takes too long. Not to mention that I also end up with <code>&lt;none&gt;</code> named images after doing this.</p> <h3>Possible Solution 3</h3> <p>Another thing I could do is not use Go in a container. I could edit and compile my project on my Mac. I would have to connect to the Postgres container from Go on my Mac. However, connecting from the host to a container is different than connecting from container to container. This would mean I&#39;d have to change my code before putting it in a container and linking it to other containers.</p> <p>Without Docker, I install all this stuff on an Ubuntu instance, for example, and then write code with <code>vim</code> and <code>entr</code>. I setup <code>entr</code> so that it autocompiles and autoruns my code. I like using <code>entr</code> because it&#39;s useful outside of Go projects as well. This allows me to experiment and make mistakes very quickly, which is nice. If possible, it would be awesome to keep this speed with Docker.</p> <p>So, does anyone have any guidance they&#39;d like to share?</p> <hr/>**评论:**<br/><br/>dewey4iv: <pre><p>Here are a few comments:</p> <p>Solution #1: You can always mount the volume and then have a filesystem watcher look for changes in the files. Recompile, kill and re-run the app. This does mean that if the blog app fails your container is left hanging BUT you could always add a little more code to make sure that process stays running. What OS are you using with your docker?</p> <p>Solution #2: Just cleanup the images once in a while. Usually, I do this (it&#39;s automated of course, like my suggestion above) and then when I&#39;m ready to deploy it I clean out everything I don&#39;t need and push the docker image up.</p> <p>Solution #3: Now imagine all of this, but automated in the container itself. </p> <p>My Experience: When I&#39;m Dev-ing out a project on my machine I usually run a Vagrant (VirtualBox) instance of CoreOS. CoreOS has GREAT support for handling a lot of the things we&#39;ve discussed with systemd and Unit Files. This also makes it REALLY easy to deploy your blog to a little CoreOS cluster or even a single machine. If you want more help let me know and I can show you exactly what I&#39;ve done. </p></pre>partkyle: <pre><p>I&#39;m actually fairly interested in this. Care to share a little example?</p></pre>om0tho: <pre><p>This would be awesome! Do you have a blog post or something I could read? Or maybe a YouTube video?</p></pre>dewey4iv: <pre><p>I&#39;ll make that next week&#39;s entry and share it with you! :) </p></pre>om0tho: <pre><p>Schweet! That&#39;d be freaking awesome! </p> <p>It kind of sucks that I&#39;m still in school because almost none of my friends even know what a Docker is, so I can&#39;t sit down with anyone. The few of us that know about Docker are total n00bs. Yay reddit!</p></pre>benjica: <pre><p><a href="https://youtu.be/5Dg0ckpmpWM?t=10s" rel="nofollow">Now I&#39;m just a small town <del>pizza</del> <strong>golang</strong> lawyer, but local development is perfectly legal!</a></p> <p>I use solution 3. I develop locally but take care to use <a href="http://play.golang.org/p/DYIih_R5X1" rel="nofollow">environment variables to pass configuration parameters to the executable</a>. That way I can configure the dev environment to properly point to dependency containers but more importantly, I can use the docker <a href="https://docs.docker.com/userguide/dockerlinks/#environment-variables" rel="nofollow">link environment variables</a> to configure the docker instance to point to docker dependencies. You shouldn&#39;t have to change your source code in order to change operating parameters. </p> <p>My Dockerfiles use a commit hash or a tag or branch to pull a copy into a sanitized container. Then I use a go get and go test ./... to confirm the build works. I use the Dockerfile to create a tagged version of the project and push it to the docker registry.</p> <p>Like <a href="/u/dewey4iv" rel="nofollow">/u/dewey4iv</a>, I use coreos to deploy containers to actual environments and this model of using environment variables helps to orchestrate those deployments as well. In the fleet service files I use tagged versions of the container along with cloud metadata to effectively put the containers where I want them.</p></pre>dewey4iv: <pre><p>Spot on. Same here. How do you work the go get ./ with subbed projects? I&#39;ve found this to be a bit annoying and I usually have to include a pre-build script (just downloads the dependencies that I need) before I get and build.</p></pre>benjica: <pre><p>I try not to use submodules. I have never heard anyone say that their lives worked out for the better because they decided to use them. A package is either part of the programs namespace if it special to the application or library worthy if it has application beyond the current use. </p> <p>It seems like an <a href="https://github.com/golang/go/issues/7764https://github.com/benjic/go/commit/f1f61fe9f5a67bb7f0e87fdfdfc539aef17808da" rel="nofollow">easy enough</a> to add the <code>--recursive</code> flag to the git command within <code>go get &lt;package&gt;</code>. It must be the hive mind at play because it is been <a href="https://github.com/golang/go/issues/7764" rel="nofollow">recently discussed</a> in the issues as well.</p> <p>I don&#39;t know though, just my two cents.</p></pre>dewey4iv: <pre><p>Hey, thanks for that. I&#39;ve actually found it useful for a sort of &#34;catch all&#34; helper package that I use from project to project. It&#39;s nothing special but it does make it easier to manage it all in ONE package rather than using 10+ repos.</p></pre>om0tho: <pre><p>Ooh, wait. If I understand you correctly, are you saying that I could mock the link env variables on my Mac? </p> <pre><code>$ WEBDB_PORT_8080_TCP_ADDR=1.2.3.4 $ WEBDB_PORT_8080_TCP_PORT=1234 $ ./myapp </code></pre> <p>That way I can still use <code>os.Getenv</code> in my Go code, like usual.</p> <p>Is that right? Or am I way off?</p></pre>benjica: <pre><p>Yeah, that is what I was getting at. Your environment is your friend. </p> <p>You would need to use the export command in your shell to make your variables persist across commands. In addition, you could use command line flags. </p> <p><code> export MYVAR=1.2.3.4 export URVAR=8000 ... </code> <a href="http://play.golang.org/p/DYIih_R5X1" rel="nofollow">http://play.golang.org/p/DYIih_R5X1</a></p></pre>dewey4iv: <pre><p>OR if you are using docker just use the ENV in your dockerfile or the -e when using docker run. <code>export</code> has seemed to work a little funky for me. Granted I&#39;m thinking that it&#39;s more due to Vagrant and how it runs it&#39;s provision commands. </p></pre>om0tho: <pre><p>Ah, cool. I didn&#39;t even know about <code>os.ExpandEnv</code>. This is great. Thanks!</p></pre>arneb3rt: <pre><p>At work we&#39;re using Docker with volumes. So you would run <code>docker exec my_app go build</code> and then just restart the container or send a HUP signal. </p></pre>om0tho: <pre><p>Hm. I tried this, but then the Nginx container couldn&#39;t forward the connections to the Go container. I&#39;m thinking the IP address for the Go container changed after <code>docker restart goapp</code>.</p></pre>arneb3rt: <pre><p>Just forward to localhost:&lt;port&gt;, as docker containers share the network interface. </p></pre>rnreekez: <pre><p>When I get back to my laptop, I&#39;ll elaborate further but I use this project to handle watch and recompile. </p> <p><a href="https://github.com/codegangsta/gin" rel="nofollow">https://github.com/codegangsta/gin</a></p></pre>dewey4iv: <pre><p>I was doing this too! The only problem, I believe, is that Gin operates as a proxy before the application. And while this is good in development it means setting up a whole different method for production as well as having a few limitations such as ports, ip addresses, etc...</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1379 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传