1"use strict";(self.webpackChunkfuf_website=self.webpackChunkfuf_website||[]).push([[347],{82726:function(e,n,t){t.r(n);var o=t(97458),s=t(61351),a=t(37193),r=t(1538),i=t(47999);const l=e=>{let{children:n,location:t,pageContext:s}=e;return(0,o.jsx)(a.Z,{location:t,children:(0,o.jsx)(r.Z,{location:t,pageContext:s,children:n})})};function c(e){const n=Object.assign({p:"p",em:"em",h2:"h2",h3:"h3",a:"a",strong:"strong",ul:"ul",li:"li",ol:"ol",span:"span"},(0,s.ah)(),e.components);return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Docker images are a powerful thing. They can save you a lot of time when it comes to development environment setup. Docker images are specified by Dockerfiles. The good thing about Dockerfiles is that they aren't written in a funky fresh new language that only the hippest developers can understand. If you feel comfortable on your bash you will be in the inner circle. OK, to be honest a little knowledge about docker magic is required too ..."}),"\n",(0,o.jsx)(n.p,{children:"As the docker adaption is moving further at Fröhlich ⧠Frei headquarters we are constantly discovering room for workflow optimization. One thing we noticed was that our Dockerfiles became a little bit too complex and that we had some duplicate Dockerfile code in different projects."}),"\n",(0,o.jsx)(n.p,{children:"Obviously it would be better to create a set of base images that have everything on board for one specific technology stack. This would allow us to maintain and improve a small set base images and to use a very minimalistic Child-Dockerfile per project that only adds project specific instructions."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.em,{children:"Makes sense ..."})}),"\n",(0,o.jsx)(n.p,{children:"The problem is that these base images have to live somewhere. We knew that docker can push images to Docker Hub, but we ignored this functionality for a while because we thought that we won't be able to maintain the images there. In the last weeks we had a second thought on that."}),"\n",(0,o.jsx)(n.p,{children:"Today I want to show you how to create your own images on Docker Hub and how maintaining them is actually fun."}),"\n",(0,o.jsx)(n.h2,{children:"Automated Builds to the rescue"}),"\n",(0,o.jsx)(n.p,{children:"A thing that always felt problematic to us was that we had to build and push images to Docker Hub from our local machines. That didn't feel like the CI approach we are trying to embrace for application development."}),"\n",(0,o.jsx)(n.p,{children:"Being able to push any local image to Docker Hub any time, overwriting the current latest version just felt wrong. I think we agree that everything used in serious development should be in version control. That's why the single point of truth for an image should be a software repository and since we are not doing anything super secret or fancy here, it should be a public one on Github. That way all changes will be traceable."}),"\n",(0,o.jsx)(n.p,{children:"OK let's get going. I will walk you through the process of how to create your own Docker Hub image backed by a Github repository."}),"\n",(0,o.jsx)(n.h3,{children:"1. Create a Github repo containing your Dockerfile"}),"\n",(0,o.jsxs)(n.p,{children:["In our case we created an image for static website development with ",(0,o.jsx)(n.a,{href:"http://jekyllrb.com",target:"_blank",rel:"nofollow noopener noreferrer",children:"jekyll"}),". You can find the repository on Github at ",(0,o.jsx)(n.a,{href:"https://github.com/froehlichundfrei/jekyll-website",target:"_blank",rel:"nofollow noopener noreferrer",children:"froehlichundfrei/jekyll-website"}),". It is based on the official docker images for ",(0,o.jsx)(n.a,{href:"https://github.com/docker-library/ruby/",target:"_blank",rel:"nofollow noopener noreferrer",children:"ruby 2.2"})," and ",(0,o.jsx)(n.a,{href:"https://github.com/nodejs/docker-node/",target:"_blank",rel:"nofollow noopener noreferrer",children:"node 0.12"}),". Have a look at the ",(0,o.jsx)(n.a,{href:"https://github.com/froehlichundfrei/jekyll-website/blob/master/Dockerfile",target:"_blank",rel:"nofollow noopener noreferrer",children:"Dockerfile"})," and you will see that we simply combined the Dockerfiles of both images."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"A little bit extra special hot sauce is also included:"})}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["python-pygments, make, openjdk-7-jre ",(0,o.jsx)(n.em,{children:"(Unix Packages)"})]}),"\n",(0,o.jsx)(n.li,{children:"jekyll, s3*website *(Ruby gems)_"}),"\n",(0,o.jsxs)(n.li,{children:["bower, gulp ",(0,o.jsx)(n.em,{children:"(Node modules)"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Further you should include a ",(0,o.jsx)(n.em,{children:"README"})," and a ",(0,o.jsx)(n.em,{children:"LICENCE"})," file. That's all we need to create a Docker Hub repository."]}),"\n",(0,o.jsx)(n.h3,{children:"2. Setup an automated build on Docker Hub"}),"\n",(0,o.jsx)(n.p,{children:"Now that the repository is existing, we have to set up the connection to Docker Hub. Actually this is not that hard."}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Create a ",(0,o.jsx)(n.a,{href:"https://hub.docker.com/",target:"_blank",rel:"nofollow noopener noreferrer",children:"Docker Hub"})," account"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"Link your Github account to the Docker Hub account"}),"\n",(0,o.jsxs)(n.p,{children:["Go to ",(0,o.jsx)(n.strong,{children:"Settings >
1 Linked Accounts & Services > Link Github"})," and link your account with the Public and Private option ",(0,o.jsx)(n.em,{children:"(otherwise you will not be able to access your organization repositories)"})]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)("div",{class:"ce-blog-image",children:(0,o.jsx)(i.t,{src:"blog/2015-08-17-how-to-set-up-automated-github-builds-for-docker-hub-images/dockerhub-connect-to-github.png",alt:"Dockerhub connect to github"})}),"\n",(0,o.jsxs)(n.ol,{start:"3",children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"Setup an Automated Build for your Github repository."}),"\n",(0,o.jsxs)(n.p,{children:["Select ",(0,o.jsx)(n.strong,{children:"Create > Create Automated Build"})," and choose your repository."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)("div",{class:"ce-blog-image",children:(0,o.jsx)(i.t,{src:"blog/2015-08-17-how-to-set-up-automated-github-builds-for-docker-hub-images/dockerhub-setup_automated_build.png",alt:"Dockerhub setup automated build"})}),"\n",(0,o.jsx)(n.p,{children:"Here you can specify which branch will be used for the Docker Hub image. In our case the master branch will trigger new builds on Docker Hub."}),"\n",(0,o.jsxs)(n.ol,{start:"4",children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"That was easy!"}),"\n",(0,o.jsxs)(n.p,{children:["Now that our Docker Hub repository is linked to our Github repository we do not have to care about building and pushing images to Docker Hub anymore. When a new commit is pushed to the master branch of our Github repository Docker Hub will automatically build a new ",(0,o.jsx)(n.em,{children:"latest"})," version of the docker image."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)("div",{class:"ce-blog-image",children:(0,o.jsx)(i.t,{src:"blog/2015-08-17-how-to-set-up-automated-github-builds-for-docker-hub-images/dockerhub-final_repository.png",alt:"Dockerhub final repository"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"NICE!"})}),"\n",(0,o.jsx)(n.h3,{children:"3. Where to go from here?"}),"\n",(0,o.jsxs)(n.p,{children:["We can now use our ",(0,o.jsx)(n.a,{href:"https://hub.docker.com/r/froehlichundfrei/jekyll-website/",target:"_blank",rel:"nofollow noopener noreferrer",children:"froehlichundfrei/jekyll-website"})," image to create a new jekyll based website. Every time we update the base image, all our projects using it will pull the latest version when they are built."]}),"\n",(0,o.jsxs)(n.p,{children:["You are welcome to take our ",(0,o.jsx)(n.em,{children:"jekyll-website"})," image for a ride and start your own instance of our blog. To do that just create a ",(0,o.jsx)(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Dockerfile</code>'}})," with the following content:"]}),"\n",(0,o.jsx)(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="dockerfile"><pre class="language-dockerfile"><code class="language-dockerfile"><span class="token instruction"><span class="token keyword">FROM</span> froehlichundfrei/jekyll-website:latest</span>\n\n<span class="token instruction"><span class="token keyword">RUN</span> git clone https://github.com/froehlichundfrei/froehlichundfrei.github.io.git /froehlichundfrei.github.io</span>\n<span class="token instruction"><span class="token keyword">WORKDIR</span> /froehlichundfrei.github.io</span>\n<span class="token instruction"><span class="token keyword">RUN</span> npm install</span>\n\n<span class="token instruction"><span class="token keyword">CMD</span> [<span class="token string">"make"</span>, <span class="token string">"serve"</span>]</span></code></pre></div>'}}),"\n",(0,o.jsx)(n.p,{children:"... and build and start the image locally:"}),"\n",(0,o.jsx)(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="shell-session"><pre class="language-shell-session"><code class="language-shell-session"><span class="token command"><span class="token shell-symbol important">#</span> <span class="token bash language-bash">build the <span class="token function">docker</span> image</span></span>\n<span class="token command"><span class="token shell-symbol important">
1#</span> <span class="token bash language-bash">browser-sync takes some <span class="token function">time</span> to <span class="token function">install</span> <span class="token punctuation">..</span>.</span></span>\n<span class="token output">docker build -t froehlichundfrei/froehlichundfrei.github.io .\n\n</span><span class="token command"><span class="token shell-symbol important">#</span> <span class="token bash language-bash">run the image</span></span>\n<span class="token output">docker run -d -p 3000:3000 --volumes-from datadock \\\n --name froehlichundfrei.github.io -h froehlichundfrei.github.io \\\n froehlichundfrei/froehlichundfrei.github.io</span></code></pre></div>'}}),"\n",(0,o.jsx)(n.p,{children:"You should now be able to access a local copy of our blog here:"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">http://<docker.host.i.p>:3000/</code>'}})," ",(0,o.jsx)(n.strong,{children:"YEAH!"})]}),"\n",(0,o.jsx)(n.h2,{children:"What do you think?"}),"\n",(0,o.jsx)(n.p,{children:"There are people who say that public docker images aren't maintained enough and that this is a security issue. Our current approach for base images is to use the official docker images as a blueprint. Perhaps it is not the best approach, but we think it is a good starting point. If you have better ideas we would really like to discuss best practices with you guys."}),"\n",(0,o.jsx)(n.p,{children:"Some stars on Github or Docker Hub would be very kind too and if you would like to suggest improvements to our jekyll-website image, feel free to create a PR on Github."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Thanks for reading!"})})]})}n.default=function(e){return void 0===e&&(e={}),(0,o.jsx)(l,Object.assign({},e,{children:(0,o.jsx)(c,e)}))}},1538:function(e,n,t){t.d(n,{Z:function(){return u}});var o=t(19949),s=t(53718),a=t(73324),r=t(41033),i=t(13725),l=t(98188),c=t(88490),h=t(97458);var u=e=>{let{children:n,location:u,pageContext:d}=e;const{author:p,categories:g,disqusIdentifier:b,disqusUrl:f,featureImg:m,title:k}=d.frontmatter,j=u.pathname,w=j.match(/^\/blog\/([0-9]+-[0-9]+-[0-9]+).*/)[1];let y=null;return y=m?m.startsWith("http")?m:t(32917)(`./img${j}${m}`).default:c.default,(0,h.jsxs)(h.Fragment,{children:[(0,h.jsxs)("header",{className:"blog-header",style:{backgroundImage:`url('${y}')`,backgroundRepeat:"no-repeat",backgroundPosition:"center center",backgroundSize:"cover"},children:[(0,h.jsxs)(l.Z,{size:1,children:[k||"TODO: Bitte Titel angeben",(0,h.jsx)("br",{}),(0,h.jsxs)("small",{children:[(0,h.jsx)(r.Z,{date:w})," von ",(0,h.jsx)(o.ZP,{name:p||"fuf",withName:!0})]})]}),(0,h.jsx)(s.Z,{categories:g})]}),(0,h.jsx)("div",{className:"markdown container\tmdxBlogPost-module--container--b1cc8",children:n}),(0,h.jsx)(i.Z,{identifier:b,shortname:"froehlichundfrei",url:u.href,urlLegacy:f,children:(0,h.jsx)(a.Z,{size:3,children:"Kommentare"})})]})}},61351:function(e,n,t){t.d(n,{ah:function(){return a}});var o=t(52983);const s=o.createContext({});function a(e){const n=o.useContext(s);return o.useMemo((()=>"function"==typeof e?e(n):{...n,...e}),[n,e])}}}]); 2//# sourceMappingURL=component---src-pages-blog-2015-08-17-how-to-set-up-automated-github-builds-for-docker-hub-images-mdx-33b3b2de362d76f98b13.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.