|
- <!DOCTYPE html>
-
- <html lang="en">
-
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
- <meta name="apple-mobile-web-app-capable" content="yes">
- <meta name="apple-mobile-web-app-status-bar-style" content="black">
- <meta name="mobile-web-app-capable" content="yes">
- <title>
- Lab 11: Docker - HackMD
- </title>
- <link rel="icon" type="image/png" href="https://hackmd.io/favicon.png">
- <link rel="apple-touch-icon" href="https://hackmd.io/apple-touch-icon.png">
-
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha256-916EbMg70RQy9LHiGkXzG8hSg9EdNy97GazNG/aiY1w=" crossorigin="anonymous" />
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.5.0/octicons.min.css" integrity="sha256-QiWfLIsCT02Sdwkogf6YMiQlj4NE84MKkzEMkZnMGdg=" crossorigin="anonymous" />
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/themes/prism.min.css" integrity="sha256-vtR0hSWRc3Tb26iuN2oZHt3KRUomwTufNIf5/4oeCyg=" crossorigin="anonymous" />
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
- <style>
- @import url(https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i|Source+Code+Pro:300,400,500|Source+Sans+Pro:300,300i,400,400i,600,600i|Source+Serif+Pro&subset=latin-ext);.hljs{background:#fff;color:#333;display:block;overflow-x:auto;padding:.5em}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-string,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#a71d5d}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-number,.hljs-symbol{color:#0086b3}.hljs-built_in,.hljs-builtin-name{color:#005cc5}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#795da3}.hljs-addition{background-color:#eaffea;color:#55a532}.hljs-deletion{background-color:#ffecec;color:#bd2c00}.hljs-link{text-decoration:underline}.markdown-body{word-wrap:break-word;font-size:16px;line-height:1.5}.markdown-body:after,.markdown-body:before{content:"";display:table}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .absent{color:#c00}.markdown-body .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-bottom:16px;margin-top:0}.markdown-body hr{background-color:#e7e7e7;border:0;height:.25em;margin:24px 0;padding:0}.markdown-body blockquote{border-left:.25em solid #ddd;color:#777;font-size:16px;padding:0 1em}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd,.popover kbd{background-color:#fcfcfc;border:1px solid;border-color:#ccc #ccc #bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb;color:#555;display:inline-block;font-size:11px;line-height:10px;padding:3px 5px;vertical-align:middle}.markdown-body .loweralpha{list-style-type:lower-alpha}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{font-weight:600;line-height:1.25;margin-bottom:16px;margin-top:24px}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#000;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1 code,.markdown-body h1 tt,.markdown-body h2 code,.markdown-body h2 tt,.markdown-body h3 code,.markdown-body h3 tt,.markdown-body h4 code,.markdown-body h4 tt,.markdown-body h5 code,.markdown-body h5 tt,.markdown-body h6 code,.markdown-body h6 tt{font-size:inherit}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{border-bottom:1px solid #eee;padding-bottom:.3em}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{color:#777;font-size:.85em}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol.no-list,.markdown-body ul.no-list{list-style-type:none;padding:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-bottom:0;margin-top:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{padding-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{font-size:1em;font-style:italic;font-weight:700;margin-top:16px;padding:0}.markdown-body dl dd{margin-bottom:16px;padding:0 16px}.markdown-body table{display:block;overflow:auto;width:100%;word-break:normal;word-break:keep-all}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{border:1px solid #ddd;padding:6px 13px}.markdown-body table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body img{background-color:#fff;box-sizing:initial;max-width:100%}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{background-color:initial;max-width:none;vertical-align:text-top}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{border:1px solid #ddd;display:block;float:left;margin:13px 0 0;overflow:hidden;padding:7px;width:auto}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{clear:both;color:#333;display:block;padding:5px 0 0}.markdown-body span.align-center{clear:both;display:block;overflow:hidden}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{clear:both;display:block;overflow:hidden}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{background-color:#0000000a;border-radius:3px;font-size:85%;margin:0;padding:.2em 0}.markdown-body code:after,.markdown-body code:before,.markdown-body tt:after,.markdown-body tt:before{content:"\00a0";letter-spacing:-.2em}.markdown-body code br,.markdown-body tt br{display:none}.markdown-body del code{text-decoration:inherit}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{background:#0000;border:0;font-size:100%;margin:0;padding:0;white-space:pre;word-break:normal}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{background-color:#f7f7f7;border-radius:3px;font-size:85%;line-height:1.45;overflow:auto;padding:16px}.markdown-body pre code,.markdown-body pre tt{word-wrap:normal;background-color:initial;border:0;display:inline;line-height:inherit;margin:0;max-width:auto;overflow:visible;padding:0}.markdown-body pre code:after,.markdown-body pre code:before,.markdown-body pre tt:after,.markdown-body pre tt:before{content:normal}.markdown-body .csv-data td,.markdown-body .csv-data th{font-size:12px;line-height:1;overflow:hidden;padding:5px;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-line-num{background:#fff;border:0;padding:10px 8px 9px;text-align:right}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{background:#f8f8f8;border-top:0;font-weight:700}.news .alert .markdown-body blockquote{border:0;padding:0 0 0 40px}.activity-tab .news .alert .commits,.activity-tab .news .markdown-body blockquote{padding-left:0}.task-list-item{list-style-type:none}.task-list-item label{font-weight:400}.task-list-item.enabled label{cursor:pointer}.task-list-item+.task-list-item{margin-top:3px}.task-list-item-checkbox{cursor:default!important;float:left;margin:.31em 0 .2em -1.3em!important;vertical-align:middle}.markdown-body{max-width:758px;overflow:visible!important;padding-bottom:40px;padding-top:40px;position:relative}.markdown-body .emoji{vertical-align:top}.markdown-body pre{border:inherit!important}.markdown-body code{color:inherit!important}.markdown-body pre code .wrapper{display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex}.markdown-body pre code .gutter{float:left;overflow:hidden;-webkit-user-select:none;user-select:none}.markdown-body pre code .gutter.linenumber{border-right:3px solid #6ce26c!important;box-sizing:initial;color:#afafaf!important;cursor:default;display:inline-block;min-width:20px;padding:0 8px 0 0;position:relative;text-align:right;z-index:4}.markdown-body pre code .gutter.linenumber>span:before{content:attr(data-linenumber)}.markdown-body pre code .code{float:left;margin:0 0 0 16px}.markdown-body .gist .line-numbers{border-bottom:none;border-left:none;border-top:none}.markdown-body .gist .line-data{border:none}.markdown-body .gist table{border-collapse:inherit!important;border-spacing:0}.markdown-body code[data-gist-id]{background:none;padding:0}.markdown-body code[data-gist-id]:after,.markdown-body code[data-gist-id]:before{content:""}.markdown-body code[data-gist-id] .blob-num{border:unset}.markdown-body code[data-gist-id] table{margin-bottom:unset;overflow:unset}.markdown-body code[data-gist-id] table tr{background:unset}.markdown-body[dir=rtl] pre{direction:ltr}.markdown-body[dir=rtl] code{direction:ltr;unicode-bidi:embed}.markdown-body .alert>p:last-child{margin-bottom:0}.markdown-body pre.abc,.markdown-body pre.flow-chart,.markdown-body pre.graphviz,.markdown-body pre.mermaid,.markdown-body pre.sequence-diagram,.markdown-body pre.vega{background-color:inherit;border-radius:0;overflow:visible;text-align:center;white-space:inherit}.markdown-body pre.abc>code,.markdown-body pre.flow-chart>code,.markdown-body pre.graphviz>code,.markdown-body pre.mermaid>code,.markdown-body pre.sequence-diagram>code,.markdown-body pre.vega>code{text-align:left}.markdown-body pre.abc>svg,.markdown-body pre.flow-chart>svg,.markdown-body pre.graphviz>svg,.markdown-body pre.mermaid>svg,.markdown-body pre.sequence-diagram>svg,.markdown-body pre.vega>svg{height:100%;max-width:100%}.markdown-body pre>code.wrap{word-wrap:break-word;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap}.markdown-body .alert>p:last-child,.markdown-body .alert>ul:last-child{margin-bottom:0}.markdown-body summary{display:list-item}.markdown-body summary:focus{outline:none}.markdown-body details summary{cursor:pointer}.markdown-body details:not([open])>:not(summary){display:none}.markdown-body figure{margin:1em 40px}.markdown-body .mark,.markdown-body mark{background-color:#fff1a7}.vimeo,.youtube{background-color:#000;background-position:50%;background-repeat:no-repeat;background-size:contain;cursor:pointer;display:table;overflow:hidden;text-align:center}.vimeo,.youtube{position:relative;width:100%}.youtube{padding-bottom:56.25%}.vimeo img{object-fit:contain;width:100%;z-index:0}.youtube img{object-fit:cover;z-index:0}.vimeo iframe,.youtube iframe,.youtube img{height:100%;left:0;position:absolute;top:0;width:100%}.vimeo iframe,.youtube iframe{vertical-align:middle;z-index:1}.vimeo .icon,.youtube .icon{color:#fff;height:auto;left:50%;opacity:.3;position:absolute;top:50%;transform:translate(-50%,-50%);transition:opacity .2s;width:auto;z-index:0}.vimeo:hover .icon,.youtube:hover .icon{opacity:.6;transition:opacity .2s}.slideshare .inner,.speakerdeck .inner{position:relative;width:100%}.slideshare .inner iframe,.speakerdeck .inner iframe{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.figma{display:table;padding-bottom:56.25%;position:relative;width:100%}.figma iframe{border:1px solid #eee;bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.markmap-container{height:300px}.markmap-container>svg{height:100%;width:100%}.MJX_Assistive_MathML{display:none}#MathJax_Message{z-index:1000!important}.ui-infobar{color:#777;margin:25px auto -25px;max-width:760px;position:relative;z-index:2}.toc .invisable-node{list-style-type:none}.ui-toc{bottom:20px;position:fixed;z-index:998}.ui-toc.both-mode{margin-left:8px}.ui-toc.both-mode .ui-toc-label{border-bottom-left-radius:0;border-top-left-radius:0;height:40px;padding:10px 4px}.ui-toc-label{background-color:#e6e6e6;border:none;color:#868686;transition:opacity .2s}.ui-toc .open .ui-toc-label{color:#fff;opacity:1;transition:opacity .2s}.ui-toc-label:focus{background-color:#ccc;color:#000;opacity:.3}.ui-toc-label:hover{background-color:#ccc;opacity:1;transition:opacity .2s}.ui-toc-dropdown{margin-bottom:20px;margin-top:20px;max-height:70vh;max-width:45vw;overflow:auto;padding-left:10px;padding-right:10px;text-align:inherit;width:25vw}.ui-toc-dropdown>.toc{max-height:calc(70vh - 100px);overflow:auto}.ui-toc-dropdown[dir=rtl] .nav{letter-spacing:.0029em;padding-right:0}.ui-toc-dropdown a{overflow:hidden;text-overflow:ellipsis;white-space:pre}.ui-toc-dropdown .nav>li>a{color:#767676;display:block;font-size:13px;font-weight:500;padding:4px 20px}.ui-toc-dropdown .nav>li:first-child:last-child>ul,.ui-toc-dropdown .toc.expand ul{display:block}.ui-toc-dropdown .nav>li>a:focus,.ui-toc-dropdown .nav>li>a:hover{background-color:initial;border-left:1px solid #000;color:#000;padding-left:19px;text-decoration:none}.ui-toc-dropdown[dir=rtl] .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav>li>a:hover{border-left:none;border-right:1px solid #000;padding-right:19px}.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a{background-color:initial;border-left:2px solid #000;color:#000;font-weight:700;padding-left:18px}.ui-toc-dropdown[dir=rtl] .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav>.active>a{border-left:none;border-right:2px solid #000;padding-right:18px}.ui-toc-dropdown .nav .nav{display:none;padding-bottom:10px}.ui-toc-dropdown .nav>.active>ul{display:block}.ui-toc-dropdown .nav .nav>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:30px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a{padding-right:30px}.ui-toc-dropdown .nav .nav>li>ul>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:40px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a{padding-right:40px}.ui-toc-dropdown .nav .nav>li>a:focus,.ui-toc-dropdown .nav .nav>li>a:hover{padding-left:29px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:hover{padding-right:29px}.ui-toc-dropdown .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>a:hover{padding-left:39px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:hover{padding-right:39px}.ui-toc-dropdown .nav .nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>a{font-weight:500;padding-left:28px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>a{padding-right:28px}.ui-toc-dropdown .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>a{font-weight:500;padding-left:38px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active>a{padding-right:38px}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-tw] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-cn] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang^=ja]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-tw]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-cn]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,MS Pゴシック,sans-serif}html[lang=zh-tw] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html[lang=zh-cn] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}html .ui-toc-dropdown[lang^=ja]{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,MS Pゴシック,sans-serif}html .ui-toc-dropdown[lang=zh-tw]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html .ui-toc-dropdown[lang=zh-cn]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}.ui-affix-toc{max-height:70vh;max-width:15vw;overflow:auto;position:fixed;top:0}.back-to-top,.expand-toggle,.go-to-bottom{color:#999;display:block;font-size:12px;font-weight:500;margin-left:10px;margin-top:10px;padding:4px 10px}.back-to-top:focus,.back-to-top:hover,.expand-toggle:focus,.expand-toggle:hover,.go-to-bottom:focus,.go-to-bottom:hover{color:#563d7c;text-decoration:none}.back-to-top,.go-to-bottom{margin-top:0}.ui-user-icon{background-position:50%;background-repeat:no-repeat;background-size:cover;border-radius:50%;display:block;height:20px;margin-bottom:2px;margin-right:5px;margin-top:2px;width:20px}.ui-user-icon.small{display:inline-block;height:18px;margin:0 0 .2em;vertical-align:middle;width:18px}.ui-infobar>small>span{line-height:22px}.ui-infobar>small .dropdown{display:inline-block}.ui-infobar>small .dropdown a:focus,.ui-infobar>small .dropdown a:hover{text-decoration:none}.ui-more-info{color:#888;cursor:pointer;vertical-align:middle}.ui-more-info .fa{font-size:16px}.ui-connectedGithub,.ui-published-note{color:#888}.ui-connectedGithub{line-height:23px;white-space:nowrap}.ui-connectedGithub a.file-path{color:#888;padding-left:22px;text-decoration:none}.ui-connectedGithub a.file-path:active,.ui-connectedGithub a.file-path:hover{color:#888;text-decoration:underline}.ui-connectedGithub .fa{font-size:20px}.ui-published-note .fa{font-size:20px;vertical-align:top}.unselectable{-webkit-user-select:none;-o-user-select:none;user-select:none}.selectable{-webkit-user-select:text;-o-user-select:text;user-select:text}.inline-spoiler-section{cursor:pointer}.inline-spoiler-section .spoiler-text{background-color:#333;border-radius:2px}.inline-spoiler-section .spoiler-text>*{opacity:0}.inline-spoiler-section .spoiler-img{filter:blur(10px)}.inline-spoiler-section.raw{background-color:#333;border-radius:2px}.inline-spoiler-section.raw>*{opacity:0}.inline-spoiler-section.unveil{cursor:auto}.inline-spoiler-section.unveil .spoiler-text{background-color:#3333331a}.inline-spoiler-section.unveil .spoiler-text>*{opacity:1}.inline-spoiler-section.unveil .spoiler-img{filter:none}@media print{blockquote,div,img,pre,table{page-break-inside:avoid!important}a[href]:after{font-size:12px!important}}.markdown-body.slides{color:#222;position:relative;z-index:1}.markdown-body.slides:before{background-color:currentColor;bottom:0;box-shadow:0 0 0 50vw;content:"";display:block;left:0;position:absolute;right:0;top:0;z-index:-1}.markdown-body.slides section[data-markdown]{background-color:#fff;margin-bottom:1.5em;position:relative;text-align:center}.markdown-body.slides section[data-markdown] code{text-align:left}.markdown-body.slides section[data-markdown]:before{content:"";display:block;padding-bottom:56.23%}.markdown-body.slides section[data-markdown]>div:first-child{left:1em;max-height:100%;overflow:hidden;position:absolute;right:1em;top:50%;transform:translateY(-50%)}.markdown-body.slides section[data-markdown]>ul{display:inline-block}.markdown-body.slides>section>section+section:after{border:3px solid #777;content:"";height:1.5em;position:absolute;right:1em;top:-1.5em}.site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,sans-serif}html[lang^=ja] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif}html[lang=zh-tw] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}body{font-smoothing:subpixel-antialiased!important;-webkit-font-smoothing:subpixel-antialiased!important;-moz-osx-font-smoothing:auto!important;-webkit-overflow-scrolling:touch;font-family:Source Sans Pro,Helvetica,Arial,sans-serif;letter-spacing:.025em}html[lang^=ja] body{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif}html[lang=zh-tw] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}abbr[data-original-title],abbr[title]{cursor:help}body.modal-open{overflow-y:auto;padding-right:0!important}svg{text-shadow:none}
- </style>
- <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
- <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
- <!--[if lt IE 9]>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js" integrity="sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=" crossorigin="anonymous"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js" integrity="sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=" crossorigin="anonymous"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js" integrity="sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=" crossorigin="anonymous"></script>
- <![endif]-->
- </head>
-
- <body>
- <div id="doc" class="markdown-body container-fluid comment-inner comment-enabled" data-hard-breaks="true"><h1 id="Lab-11-Docker" data-id="Lab-11-Docker" style=""><a class="anchor hidden-xs" href="#Lab-11-Docker" title="Lab-11-Docker"><span class="octicon octicon-link"></span></a><span>Lab 11: Docker</span></h1><h2 id="Task-1-Install-Docker-on-Ubuntu" data-id="Task-1-Install-Docker-on-Ubuntu" style=""><a class="anchor hidden-xs" href="#Task-1-Install-Docker-on-Ubuntu" title="Task-1-Install-Docker-on-Ubuntu"><span class="octicon octicon-link"></span></a><span>Task 1: Install Docker on Ubuntu</span></h2><ul>
- <li><span>Update the list of packages:</span><pre><code>$ sudo apt update
- </code></pre>
- </li>
- <li><span>Install Docker:</span><pre><code>$ sudo apt install docker.io
- </code></pre>
- </li>
- <li><span>Docker should now be installed, the daemon started, and the process enabled to start on boot. Check that it’s running:</span><pre><code>$ sudo systemctl status docker
- </code></pre>
- </li>
- </ul><p><span>It is recommended that you do not run docker as the root user. If you currently cannot run </span><code>$ docker</code><span> with your non-root account, then take the following steps:</span></p><ul>
- <li><span>Add your username to the docker group:</span><pre><code>$ sudo usermod -aG docker ${USER}
- </code></pre>
- </li>
- <li><span>To apply the new group membership, log out of the server and back in, or type the following:</span><pre><code>$ su - ${USER}
- </code></pre>
- </li>
- <li><span>Confirm that your user is now added to the docker group by typing </span><code>$ groups</code><span>.</span><pre><code>$ groups
- user2 adm cdrom sudo dip plugdev lpadmin lxd sambashare docker
- </code></pre>
- </li>
- </ul><blockquote>
- <p><span>If you need to add a user to the docker group that you’re not logged in as, declare that username explicitly using:</span></p>
- <pre><code>$ sudo usermod -aG docker <username>
- </code></pre>
- </blockquote><h2 id="Task-2-Pull-images-and-run-containers" data-id="Task-2-Pull-images-and-run-containers" style=""><a class="anchor hidden-xs" href="#Task-2-Pull-images-and-run-containers" title="Task-2-Pull-images-and-run-containers"><span class="octicon octicon-link"></span></a><span>Task 2: Pull images and run containers</span></h2><ul>
- <li><span>Locate the application you want to run on Docker hub. Let’s run the Docker </span><code>hello-world</code><span> application </span><a href="https://hub.docker.com/_/hello-world" target="_blank" rel="noopener"><span>https://hub.docker.com/_/hello-world</span></a><span>.</span><pre><code>$ docker run hello-world
- </code></pre>
- <span>Docker will first search locally for the </span><code>hello-world</code><span> image. It will then download the image from Docker Hub if it is not found locally.</span><pre><code>Unable to find image 'hello-world:latest' locally
- latest: Pulling from library/hello-world
- 2db29710123e: Pull complete
- Digest: sha256:faa03e786c97f07ef34423fccceeec2398ec8a5759259f94d99078f264e9d7af
- Status: Downloaded newer image for hello-world:latest
-
- Hello from Docker!
- This message shows that your installation appears to be working correctly.
- ...
- </code></pre>
- <blockquote>
- <p><span>Docker Hub is the default repository for Docker installations.</span></p>
- </blockquote>
- </li>
- <li><span>You can search for images available on the Docker Hub by using the </span><code>search</code><span> option. Let’s search for “nginx”:</span><pre><code>$ docker search nginx
- </code></pre>
- <img src="https://i.imgur.com/5SL5esj.png" alt="" loading="lazy"></li>
- <li><span>Let’s download the </span><code>nginx</code><span> image to our machine without running it. Use the </span><code>pull</code><span> option:</span><pre><code>$ docker pull nginx
- </code></pre>
- </li>
- <li><span>To see all images downloaded to your machine run:</span><pre><code>$ docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- nginx latest 76c69feac34e 2 weeks ago 142MB
- hello-world latest feb5d9fea6a5 13 months ago 13.3kB
- </code></pre>
- </li>
- <li><span>Unlike the </span><code>hello-world</code><span> container that ran once and exited, some containers run endlessly and their logs are written to the terminal. We can run these containers in the background or in detached mode with the </span><code>-d</code><span> flag. Let’s run </span><code>nginx</code><span> in the background</span><pre><code>$ docker run -d nginx
- </code></pre>
- </li>
- <li><span>Run </span><code>$ docker ps</code><span> to view active containers.</span><pre><code>$ docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- f2e1f7608e47 nginx "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 80/tcp sweet_clarke
- </code></pre>
- <blockquote>
- <p><span>The </span><code>hello-world</code><span> application we ran earlier does not run continuously. It simply prints the message and exits.</span></p>
- </blockquote>
- </li>
- <li><span>To view all containers (active and inactive), run </span><code>$ docker ps -a</code><pre><code>$ docker ps -a
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- f2e1f7608e47 nginx "/docker-entrypoint.…" 33 seconds ago Up 32 seconds 80/tcp sweet_clarke
- 6e4d35a225ec hello-world "/hello" About a minute ago Exited (0) About a minute ago gallant_edison
- </code></pre>
- <blockquote>
- <p><span>You can interact with a container by using the container ID or the unique container name. For example, the container ID and container name of the container created from the </span><code>nginx</code><span> image is </span><code>f2e1f7608e47</code><span> and </span><code>sweet_clarke</code><span> respectively.</span></p>
- </blockquote>
- </li>
- <li><span>To enter the shell of a running container and execute commands, run </span><code>$ docker exec -it <container-name> bash</code><span>:</span><pre><code>$ docker exec -it sweet_clarke bash
- root@f2e1f7608e47:/#
- </code></pre>
- </li>
- <li><span>While in the container, view nginx default index file:</span><pre><code>root@f2e1f7608e47:/# cat /usr/share/nginx/html/index.html
- <!DOCTYPE html>
- <html>
- <head>
- <title>Welcome to nginx!</title>
- <style>
- html { color-scheme: light dark; }
- body { width: 35em; margin: 0 auto;
- font-family: Tahoma, Verdana, Arial, sans-serif; }
- </style>
- </head>
- <body>
- <h1>Welcome to nginx!</h1>
- <p>If you see this page, the nginx web server is successfully installed and
- working. Further configuration is required.</p>
-
- <p>For online documentation and support please refer to
- <a href="http://nginx.org/">nginx.org</a>.<br/>
- Commercial support is available at
- <a href="http://nginx.com/">nginx.com</a>.</p>
-
- <p><em>Thank you for using nginx.</em></p>
- </body>
- </html>
- </code></pre>
- <span>Navigate the shell to see its capabilities. Administrators can make changes to the Docker applications they deploy by entering the container shell.</span></li>
- <li><span>When done exploring the container shell, run </span><code>$ exit</code><span> to close the shell and return to your host machine.</span></li>
- <li><span>To stop a container, run </span><code>$ docker stop <cotainer-name></code><span>. Let’s stop the </span><code>sweet_clarke</code><span> container:</span><pre><code>$ docker stop sweet_clarke
- </code></pre>
- </li>
- <li><span>View a list of all containers again. The status should show that it exited.</span><pre><code>$ docker ps -a
- </code></pre>
- </li>
- <li><span>You can restart a stopped container by running: </span><code>$ docker start <cotainer-name></code><span>.</span>
- <blockquote>
- <p><strong><span>Note</span></strong><span> that </span><code>$ docker run <image-name></code><span> creates a new container, therefore it’s not necessary to use </span><code>docker run</code><span> when the container is already created from the image, unless your intention is to create multiple containers.</span></p>
- </blockquote>
- </li>
- <li><span>You can remove a container with </span><code>$ docker rm <container-name></code><span>.</span><pre><code>$ docker rm sweet_clarke
- $ docker rm 6e4d35a225ec # container ID for hello-world
- </code></pre>
- </li>
- <li><span>Let’s also remove the </span><code>hello-world</code><span> and the </span><code>nginx</code><span> images from our local machine.</span><br>
- <span>First, view available images:</span><pre><code>$ docker images -a
- REPOSITORY TAG IMAGE ID CREATED SIZE
- hello-world latest feb5d9fea6a5 13 months ago 13.3kB
- nginx latest f2e1f7608e47 2 years ago 100.2MB
- </code></pre>
- <span>Use the </span><code>rmi</code><span> option to remove the images:</span><pre><code>$ docker rmi hello-world nginx
- Untagged: hello-world:latest
- Untagged: hello-world@sha256:faa03e786c97f07ef34423fccceeec2398ec8a5759259f94d99078f264e9d7af
- Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
- Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
- Untagged: nginx:latest
- Untagged: nginx@sha256:943c25b4b66b332184d5ba6bb18234273551593016c0e0ae906bab111548239f
- Deleted: sha256:76c69feac34e85768b284f84416c3546b240e8cb4f68acbbe5ad261a8b36f39f
- Deleted: sha256:8b811a30cb94c227fb2ae61a2a1ec1e93381dbef06f9ea6b5c06df4f27651fed
- Deleted: sha256:470cc6f5d954afeb2695504eff0eda9f8da0e1b3b8bde30e74d9c48dbcb99906
- Deleted: sha256:1c277c746c47ba650267f58cc6e1ea430ce726065c79691ce04235d90209caff
- Deleted: sha256:953e18d40076df9e65564241b34cfba85ab1a6c0634c67e92d6a1f633c5b97d9
- Deleted: sha256:f0a780360f49b2b6afc28882ed2399799e6615862e7dc64451fb3688a33fe712
- Deleted: sha256:a12586ed027fafddcddcc63b31671f406c25e43342479fc92a330e7e30d65f2e
- </code></pre>
- </li>
- </ul><h2 id="Task-3-Create-a-custom-Docker-image" data-id="Task-3-Create-a-custom-Docker-image" style=""><a class="anchor hidden-xs" href="#Task-3-Create-a-custom-Docker-image" title="Task-3-Create-a-custom-Docker-image"><span class="octicon octicon-link"></span></a><span>Task 3: Create a custom Docker image</span></h2><p><span>Let’s create a static page website and run it on a Python web server.</span></p><blockquote>
- <p><strong><span>Note:</span></strong><span> There are more effective ways to set up a web server. We use the methods in this lab simply to explore the process of creating a Docker image.</span></p>
- </blockquote><ul>
- <li><span>Create a directory for the Docker application and navigate to it:</span><pre><code>$ mkdir ~/pythonweb && cd ~/pythonweb
- </code></pre>
- </li>
- <li><span>Create a </span><code>Dockerfile</code><span> in the directory:</span><pre><code>$ touch Dockerfile
- </code></pre>
- </li>
- <li><span>Add the following lines to </span><code>Dockerfile</code><span>:</span>
- <ol>
- <li><span>To pull the docker image for Ubuntu 22.04:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">FROM ubuntu:jammy
- </div></div></code></pre>
- </li>
- <li><span>To update the sources list and install python3:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">RUN apt-get update && apt-get install -y python3 --no-install-recommends
- </div></div></code></pre>
- </li>
- </ol>
- <blockquote>
- <p><span>The python web server listens on port </span><code>8000</code><span> by default. Network access to container services is disabled by default.</span></p>
- </blockquote>
- <ol start="4">
- <li><span>To expose port </span><code>8000</code><span> to devices outside the container</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">EXPOSE 8000
- </div></div></code></pre>
- </li>
- <li><span>To start the python web server when the contaner is executed:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">ENTRYPOINT ["python3", "-m", "http.server"]
- </div></div></code></pre>
- </li>
- </ol>
- <span>The </span><code>Dockerfile</code><span> should look like this:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
- <span></span>
- <span></span>
- <span></span></div><div class="code">FROM ubuntu:jammy
- RUN apt-get update && apt-get install -y python3 --no-install-recommends
- EXPOSE 8000
- ENTRYPOINT ["python3", "-m", "http.server"]
- </div></div></code></pre>
- <blockquote>
- <p><code>RUN</code><span> is used to specify commands that should be run when building the image.</span><br>
- <code>ENTRYPOINT</code><span> and </span><code>CMD</code><span> define commands the container executes when it launches.</span></p>
- </blockquote>
- </li>
- <li><span>Build the image:</span><pre><code>docker build -t pythonweb:latest .
- </code></pre>
- <blockquote>
- <p><span>The </span><code>.</code><span> at the end represents the location of the </span><code>Dockerfile</code><span>. In this case it is in the CWD. Otherwise, we would have specified the directory where the </span><code>Dockerfile</code><span> is located.</span></p>
- </blockquote>
- </li>
- <li><span>Check your docker images and you should see something similar to the following:</span><pre><code>$ docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- pythonweb latest 60e7915677a4 About a minute ago 147MB
- ubuntu jammy a8780b506fa4 10 days ago 77.8MB
- </code></pre>
- </li>
- <li><span>Run the image </span><code>pythonweb</code><span> and map port 80 on the host machine to port 8000 on the container. This will allow users interact with the web server in the container via the host machine.</span><pre><code>$ docker run -p 80:8000 -d pythonweb
- </code></pre>
- </li>
- <li><span>View the contents of the web server in your browser:</span><br>
- <img src="https://i.imgur.com/O10RFHK.png" alt="" loading="lazy"><br>
- <span>The Python web server works, but there is no index page, and it shows system files. Let’s proceed to create an index web page, add a working directory, and update the image with the new configuration.</span></li>
- <li><span>Create a directory to contain the web files.</span><pre><code>$ mkdir ~/pythonweb/webfiles/
- </code></pre>
- </li>
- <li><span>Create </span><code>index.html</code><span> in </span><code>~/pythonweb/webfiles/index.html</code><span>:</span><pre><code>$ vi ~/pythonweb/webfiles/index.html
- </code></pre>
- <span>Add the following lines to the file:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
- <span></span>
- <span></span>
- <span></span></div><div class="code"><html>
- <h1>SNA Lab</h1>
- <p>SNA rocks :)</p>
- </html>
- </div></div></code></pre>
- </li>
- <li><span>Modify the </span><code>Dockerfile</code><span> and add the following lines:</span>
- <ol>
- <li><span>To copy the contents of </span><code>webfiles</code><span> directory to the image:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">COPY webfiles/ /usr/share/webfiles
- </div></div></code></pre>
- </li>
- <li><span>To change the container working directory to the </span><code>/usr/share/webfiles</code><span> directory</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">WORKDIR /usr/share/webfiles
- </div></div></code></pre>
- </li>
- </ol>
- <span>The final </span><code>Dockerfile</code><span> after the modification is shown below:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
- <span></span>
- <span></span>
- <span></span>
- <span></span>
- <span></span></div><div class="code">FROM ubuntu:jammy
- RUN apt-get update && apt-get install -y python3 --no-install-recommends
- COPY webfiles/ /usr/share/webfiles
- WORKDIR /usr/share/webfiles
- EXPOSE 8000
- ENTRYPOINT ["python3", "-m", "http.server"]
- </div></div></code></pre>
- </li>
- <li><span>Check running containers, stop the container running </span><code>pythonweb</code><span>, and remove the container:</span><pre><code>$ docker ps -a
- $ docker stop <container-name>
- $ docker rm <container-name>
- </code></pre>
- </li>
- <li><span>Remove the </span><code>pythonweb</code><span> image.</span><pre><code>$ docker rmi pythonweb
- </code></pre>
- </li>
- <li><span>Build the image</span><pre><code>docker build -t pythonweb:latest .
- </code></pre>
- </li>
- <li><span>Run the updated </span><code>pythonweb</code><span> image. This time, let’s specify a container name with the </span><code>--name</code><span> flag. This is better than relying on the random names generated by Docker:</span><pre><code>$ docker run -p 80:8000 -d --name snaweb-container pythonweb
- </code></pre>
- <span>Run </span><code>docker ps</code><span> to view the running container:</span><pre><code>$ docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- ecfb00c4039f pythonweb "python3 -m http.ser…" 6 seconds ago Up 5 seconds 0.0.0.0:80->8000/tcp, :::80->8000/tcp snaweb-container
- </code></pre>
- </li>
- <li><span>Visit the page again and you should have results similar to the following:</span><br>
- <img src="https://i.imgur.com/jRd5Wq8.png" alt="" loading="lazy"></li>
- </ul><h2 id="Task-4-Docker-inspect-and-container-logs" data-id="Task-4-Docker-inspect-and-container-logs" style=""><a class="anchor hidden-xs" href="#Task-4-Docker-inspect-and-container-logs" title="Task-4-Docker-inspect-and-container-logs"><span class="octicon octicon-link"></span></a><span>Task 4: Docker </span><code>inspect</code><span> and container logs</span></h2><p><span>Docker </span><code>inspect</code><span> is used to view low-level information on Docker objects.</span></p><ul>
- <li><span>Inspect the </span><code>snaweb-container</code><span> container:</span><pre><code>$ docker inspect snaweb-container
- </code></pre>
- <span>The result is JSON data that contains some useful information if analyzed properly.</span><br>
- <span>You can filter the results from </span><code>inspect</code><span> without manually reading everything in the large volume of output it generates.</span></li>
- <li><span>Get the full container ID for </span><code>snaweb-container</code><span>:</span><pre><code>docker container inspect -f '{{.Id}}' snaweb-container
- </code></pre>
- </li>
- <li><span>View the containers main process:</span><pre><code>$ docker container inspect -f '{{printf "%s " .Path}}{{range .Args}}{{printf "%s " .}}{{end}}' snaweb-container
- </code></pre>
- </li>
- <li><span>List all port bindings:</span><pre><code>$ docker container inspect -f '{{range $target, $published := .NetworkSettings.Ports}}{{range $published}}{{printf "%s -> %s:%s\n" $target .HostIp .HostPort}}{{end}}{{end}}' snaweb-container
- </code></pre>
- </li>
- <li><span>View the network your container is connected to:</span><pre><code>$ docker inspect -f "{{json .NetworkSettings.Networks }}" snaweb-container
- </code></pre>
- <span>The sample output shows that my container is connected to the </span><code>bridge</code><span> network:</span><pre><code>{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"ece6245e2975ad3a709dbf7d993a59454c703f09c68b892fd3922581ed967a8e","EndpointID":"40fd7af8985dba6f7f654bffef4df2de363db00b360f630ee19d2d78704df5a1","Gateway":"172.17.0.1","IPAddress":"172.17.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02","DriverOpts":null}}
- </code></pre>
- </li>
- <li><span>List the containers connected to a network along with their IP addresses:</span>
- <blockquote>
- <p><span>Replace </span><code>bridge</code><span> in the command with your network name.</span></p>
- </blockquote>
- <pre><code>$ docker network inspect -f '{{range .Containers}}{{printf "%s -> %s\n" .Name .IPv4Address}}{{end}}' bridge
- </code></pre>
- </li>
- </ul><p><span>Container logging helps developers keep track of patterns, troubleshoot issues, and fix bugs.</span></p><ul>
- <li><span>View the container logs with </span><code>$ docker logs <container-name></code><span>:</span><pre><code>$ docker logs snaweb-container
- </code></pre>
- </li>
- <li><span>Container logs are stored in the </span><code>/var/lib/docker/containers/ID/ID-json.log</code><span>.</span></li>
- <li><span>Use </span><code>inspect</code><span> to find the full log path for </span><code>snaweb-container</code><span>:</span><pre><code>$ docker container inspect -f '{{.LogPath}}' snaweb-container
- </code></pre>
- <span>View the log file with tail:</span><pre><code>$ sudo tail /var/lib/docker/containers/ecfb00c4039fddb81a5185fd2287a908cefd140e8f1d832ab65a71759aac39ce/ecfb00c4039fddb81a5185fd2287a908cefd140e8f1d832ab65a71759aac39ce-json.log
- {"log":"172.17.0.1 - - [13/Nov/2022 16:34:00] \"GET / HTTP/1.1\" 200 -\n","stream":"stderr","time":"2022-11-13T16:34:00.810777628Z"}
- {"log":"172.17.0.1 - - [13/Nov/2022 16:48:49] \"GET / HTTP/1.1\" 304 -\n","stream":"stderr","time":"2022-11-13T16:48:49.9306387Z"}
- {"log":"192.168.132.1 - - [13/Nov/2022 16:49:11] \"GET / HTTP/1.1\" 200 -\n","stream":"stderr","time":"2022-11-13T16:49:11.494390274Z"}
- {"log":"192.168.132.1 - - [13/Nov/2022 16:49:11] code 404, message File not found\n","stream":"stderr","time":"2022-11-13T16:49:11.584257708Z"}
- {"log":"192.168.132.1 - - [13/Nov/2022 16:49:11] \"GET /favicon.ico HTTP/1.1\" 404 -\n","stream":"stderr","time":"2022-11-13T16:49:11.584310308Z"}
- </code></pre>
- </li>
- </ul><h2 id="Questions-to-answer" data-id="Questions-to-answer" style=""><a class="anchor hidden-xs" href="#Questions-to-answer" title="Questions-to-answer"><span class="octicon octicon-link"></span></a><span>Questions to answer</span></h2><ol>
- <li><span>Compare and contrast </span><code>ENTRYPOINT</code><span> and </span><code>CMD</code><span> in Dockerfile. In what situation would you use each of them?</span></li>
- <li><span>List five security precautions you will take when building or deploying a Docker resource (image or container).</span></li>
- <li><span>Show a single line command that will remove all exited Docker containers. Do not use any text filtering editor. Show test results.</span></li>
- <li><span>Show how you can copy files to a running container without entering the container’s interactive shell.</span></li>
- <li><span>Create a dockerized web application running on nginx. The web index page </span><code>index.html</code><span> should be located on your host machine. The directory containing the index page should be mounted to the container and served from there.</span>
- <blockquote>
- <p><span>This means that you should be able to modify the web index page on your host machine without interacting with the container.</span><br>
- <span>Show all steps taken for the configuration including the test results.</span></p>
- </blockquote>
- </li>
- <li><span>Setup rsyslog on your host machine as a central logging server. Create a Docker container and configure it to forward its log to your central logging server.</span>
- <blockquote>
- <p><span>Show steps and test results.</span></p>
- </blockquote>
- </li>
- </ol><h3 id="Bonus" data-id="Bonus" style=""><a class="anchor hidden-xs" href="#Bonus" title="Bonus"><span class="octicon octicon-link"></span></a><span>Bonus</span></h3><ol start="7">
- <li><span>Dockerize any open source application of your choice, and host it on Docker hub. Share link to the repository.</span></li>
- <li><span>Find and fix the problems in the following Dockerfile. There are some issues building the image and also running the container:</span><pre><code class="hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
- <span></span>
- <span></span>
- <span></span>
- <span></span></div><div class="code">FROM alpine
- RUN apt-get update && apt-get install -y python3 --no-install-recommends
- RUN touch index.html
- RUN echo "<html><h1>Testing web</h1></html>" >> index.html
- CMD ["python", "-m", "http.server"]
- </div></div></code></pre>
- <blockquote>
- <p><span>Show all steps taken to fix it, and a working solution.</span></p>
- </blockquote>
- </li>
- </ol></div>
- <div class="ui-toc dropup unselectable hidden-print" style="display:none;">
- <div class="pull-right dropdown">
- <a id="tocLabel" class="ui-toc-label btn btn-default" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false" title="Table of content">
- <i class="fa fa-bars"></i>
- </a>
- <ul id="ui-toc" class="ui-toc-dropdown dropdown-menu" aria-labelledby="tocLabel">
- <div class="toc"><ul class="nav">
- <li class=""><a href="#Lab-11-Docker" title="Lab 11: Docker">Lab 11: Docker</a><ul class="nav">
- <li class=""><a href="#Task-1-Install-Docker-on-Ubuntu" title="Task 1: Install Docker on Ubuntu">Task 1: Install Docker on Ubuntu</a></li>
- <li class=""><a href="#Task-2-Pull-images-and-run-containers" title="Task 2: Pull images and run containers">Task 2: Pull images and run containers</a></li>
- <li><a href="#Task-3-Create-a-custom-Docker-image" title="Task 3: Create a custom Docker image">Task 3: Create a custom Docker image</a></li>
- <li><a href="#Task-4-Docker-inspect-and-container-logs" title="Task 4: Docker inspect and container logs">Task 4: Docker inspect and container logs</a></li>
- <li><a href="#Questions-to-answer" title="Questions to answer">Questions to answer</a><ul class="nav">
- <li><a href="#Bonus" title="Bonus">Bonus</a></li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
- </ul>
- </div>
- </div>
- <div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;" null null>
- <div class="toc"><ul class="nav">
- <li class=""><a href="#Lab-11-Docker" title="Lab 11: Docker">Lab 11: Docker</a><ul class="nav">
- <li class=""><a href="#Task-1-Install-Docker-on-Ubuntu" title="Task 1: Install Docker on Ubuntu">Task 1: Install Docker on Ubuntu</a></li>
- <li class=""><a href="#Task-2-Pull-images-and-run-containers" title="Task 2: Pull images and run containers">Task 2: Pull images and run containers</a></li>
- <li><a href="#Task-3-Create-a-custom-Docker-image" title="Task 3: Create a custom Docker image">Task 3: Create a custom Docker image</a></li>
- <li><a href="#Task-4-Docker-inspect-and-container-logs" title="Task 4: Docker inspect and container logs">Task 4: Docker inspect and container logs</a></li>
- <li><a href="#Questions-to-answer" title="Questions to answer">Questions to answer</a><ul class="nav">
- <li><a href="#Bonus" title="Bonus">Bonus</a></li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
- </div>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha256-U5ZEeKfGNOja007MMD3YBI0A3OSZOQbeG6z2f2Y0hu8=" crossorigin="anonymous" defer></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
- <script>
- var markdown = $(".markdown-body");
- //smooth all hash trigger scrolling
- function smoothHashScroll() {
- var hashElements = $("a[href^='#']").toArray();
- for (var i = 0; i < hashElements.length; i++) {
- var element = hashElements[i];
- var $element = $(element);
- var hash = element.hash;
- if (hash) {
- $element.on('click', function (e) {
- // store hash
- var hash = this.hash;
- if ($(hash).length <= 0) return;
- // prevent default anchor click behavior
- e.preventDefault();
- // animate
- $('body, html').stop(true, true).animate({
- scrollTop: $(hash).offset().top
- }, 100, "linear", function () {
- // when done, add hash to url
- // (default click behaviour)
- window.location.hash = hash;
- });
- });
- }
- }
- }
-
- smoothHashScroll();
- var toc = $('.ui-toc');
- var tocAffix = $('.ui-affix-toc');
- var tocDropdown = $('.ui-toc-dropdown');
- //toc
- tocDropdown.click(function (e) {
- e.stopPropagation();
- });
-
- var enoughForAffixToc = true;
-
- function generateScrollspy() {
- $(document.body).scrollspy({
- target: ''
- });
- $(document.body).scrollspy('refresh');
- if (enoughForAffixToc) {
- toc.hide();
- tocAffix.show();
- } else {
- tocAffix.hide();
- toc.show();
- }
- $(document.body).scroll();
- }
-
- function windowResize() {
- //toc right
- var paddingRight = parseFloat(markdown.css('padding-right'));
- var right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight));
- toc.css('right', right + 'px');
- //affix toc left
- var newbool;
- var rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2;
- //for ipad or wider device
- if (rightMargin >= 133) {
- newbool = true;
- var affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2;
- var left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin;
- tocAffix.css('left', left + 'px');
- } else {
- newbool = false;
- }
- if (newbool != enoughForAffixToc) {
- enoughForAffixToc = newbool;
- generateScrollspy();
- }
- }
- $(window).resize(function () {
- windowResize();
- });
- $(document).ready(function () {
- windowResize();
- generateScrollspy();
- });
-
- //remove hash
- function removeHash() {
- window.location.hash = '';
- }
-
- var backtotop = $('.back-to-top');
- var gotobottom = $('.go-to-bottom');
-
- backtotop.click(function (e) {
- e.preventDefault();
- e.stopPropagation();
- if (scrollToTop)
- scrollToTop();
- removeHash();
- });
- gotobottom.click(function (e) {
- e.preventDefault();
- e.stopPropagation();
- if (scrollToBottom)
- scrollToBottom();
- removeHash();
- });
-
- var toggle = $('.expand-toggle');
- var tocExpand = false;
-
- checkExpandToggle();
- toggle.click(function (e) {
- e.preventDefault();
- e.stopPropagation();
- tocExpand = !tocExpand;
- checkExpandToggle();
- })
-
- function checkExpandToggle () {
- var toc = $('.ui-toc-dropdown .toc');
- var toggle = $('.expand-toggle');
- if (!tocExpand) {
- toc.removeClass('expand');
- toggle.text('Expand all');
- } else {
- toc.addClass('expand');
- toggle.text('Collapse all');
- }
- }
-
- function scrollToTop() {
- $('body, html').stop(true, true).animate({
- scrollTop: 0
- }, 100, "linear");
- }
-
- function scrollToBottom() {
- $('body, html').stop(true, true).animate({
- scrollTop: $(document.body)[0].scrollHeight
- }, 100, "linear");
- }
- </script>
- </body>
-
- </html>
|