166 |
174 |
175 |
176 |
177 | );
178 | }
179 |
180 | ReactDOM.render(, document.getElementById('root'));
181 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | # Quick verify of the mkdocs config
6 | echo "Verifying mkdocs config"
7 | docker run --rm -tiv $PWD:/app -w /app node:alpine node verify.js
8 |
9 | # Validate tests are passing for the app
10 | echo "Running tests for the app"
11 | docker run --rm -tiv $PWD/app:/app -w /app node:alpine sh -c "yarn install && yarn test"
12 |
13 | if [ $1 == "--push" ]; then
14 | WILL_PUSH=1
15 | else
16 | WILL_PUSH=0
17 | fi
18 |
19 | # Build each language and, you know, multi-arch it!
20 | for language in `find . -type d -maxdepth 1 | grep docs | cut -d '_' -f 2`; do
21 | echo "Going to build image for $language"
22 |
23 | docker buildx build \
24 | --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 \
25 | --build-arg LANGUAGE=$language \
26 | -t dockersamples/101-tutorial:$language \
27 | $( (( $WILL_PUSH == 1 )) && printf %s '--push' ) .
28 | done
29 |
30 | # Retag "en" as latest
31 | docker buildx build \
32 | --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 \
33 | --build-arg LANGUAGE=en \
34 | -t dockersamples/101-tutorial:latest \
35 | $( (( $WILL_PUSH == 1 )) && printf %s '--push' ) .
36 |
--------------------------------------------------------------------------------
/configure.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const YAML = require('yaml');
3 | const { stringifyString } = require('yaml/util');
4 |
5 | const language = process.argv[2];
6 | console.log(`Configuring mkdocs for ${language}`);
7 |
8 | const languageData = require('./mkdocs-config.json')[language];
9 | if (!languageData) {
10 | console.error("Unable to find language config");
11 | process.exit(1);
12 | }
13 |
14 | const mkdocData = YAML.parse(fs.readFileSync('mkdocs.yml').toString());
15 | mkdocData['docs_dir'] = `/app/docs_${language}`;
16 | mkdocData['site_description'] = languageData.site_description;
17 | mkdocData.theme.language = languageData.language_code;
18 |
19 | mkdocData.nav = [
20 | {
21 | [languageData.nav.Tutorial.title] : [
22 | { [languageData.nav['Getting Started'].title] : `${languageData.tutorial_dir_name}/index.md`, },
23 | { [languageData.nav['Our Application'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Our Application'].dir_name}/index.md` },
24 | { [languageData.nav['Updating our App'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Updating our App'].dir_name}/index.md` },
25 | { [languageData.nav['Sharing our App'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Sharing our App'].dir_name}/index.md` },
26 | { [languageData.nav['Persisting our DB'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Persisting our DB'].dir_name}/index.md` },
27 | { [languageData.nav['Using Bind Mounts'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Using Bind Mounts'].dir_name}/index.md` },
28 | { [languageData.nav['Multi-Container Apps'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Multi-Container Apps'].dir_name}/index.md` },
29 | { [languageData.nav['Using Docker Compose'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Using Docker Compose'].dir_name}/index.md` },
30 | { [languageData.nav['Image Building Best Practices'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['Image Building Best Practices'].dir_name}/index.md` },
31 | { [languageData.nav['What Next?'].title] : `${languageData.tutorial_dir_name}/${languageData.nav['What Next?'].dir_name}/index.md` },
32 | ],
33 | },
34 | {
35 | [languageData.nav['PWD Tips'].title] : `${languageData.nav['PWD Tips'].dir_name}/index.md`
36 | },
37 | ];
38 |
39 | fs.writeFileSync("mkdocs-configured.yml", YAML.stringify(mkdocData));
40 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.7"
2 |
3 | services:
4 | docs:
5 | build:
6 | context: .
7 | dockerfile: Dockerfile
8 | target: dev
9 | args:
10 | LANGUAGE: en
11 | ports:
12 | - 8000:8000
13 | volumes:
14 | - ./:/app
15 |
--------------------------------------------------------------------------------
/docs_en/css/dark-mode.css:
--------------------------------------------------------------------------------
1 | @media (prefers-color-scheme: dark) {
2 | .md-main {
3 | color: rgba(255, 255, 255, 0.75) !important;
4 | background-color: #36393e !important;
5 | }
6 |
7 | article img {
8 | box-shadow: 0 0 1em #000;
9 | }
10 |
11 | .md-main h1 {
12 | color: rgba(255, 255, 255, 0.8) !important;
13 | }
14 | blockquote {
15 | color: rgba(255, 255, 255, 0.75) !important;
16 | }
17 | table {
18 | background-color: #616161 !important;
19 | }
20 | tbody {
21 | background-color: #484848 !important;
22 | }
23 | .md-sidebar__scrollwrap::-webkit-scrollbar-thumb {
24 | background-color: #e0e0e0 !important;
25 | }
26 | .md-nav {
27 | color: rgba(255, 255, 255, 0.8) !important;
28 | background-color: #36393e !important;
29 | }
30 | html .md-nav--primary .md-nav__title:before {
31 | color: #fafafa !important;
32 | }
33 | .md-nav__title {
34 | color: rgba(255, 255, 255, 0.9) !important;
35 | background-color: #36393e !important;
36 | }
37 | .md-nav--primary .md-nav__link:after {
38 | color: #fafafa !important;
39 | }
40 | .md-nav__list {
41 | color: rgba(255, 255, 255, 0.8) !important;
42 | background-color: #36393e !important;
43 | }
44 | .md-nav__item {
45 | color: rgba(255, 255, 255, 0.7) !important;
46 | background-color: #36393e !important;
47 | }
48 | .md-search__scrollwrap::-webkit-scrollbar-thumb {
49 | background-color: #e0e0e0 !important;
50 | }
51 | .md-search__scrollwrap {
52 | background-color: #44484e !important;
53 | }
54 | .md-search-result__article--document:before {
55 | color: #eee !important;
56 | }
57 | .md-search-result__list {
58 | color: #eee !important;
59 | background-color: #36393e !important;
60 | }
61 | .md-search-result__meta {
62 | background-color: #eee !important;
63 | }
64 | .md-search-result__teaser {
65 | color: #bdbdbd !important;
66 | }
67 | .md-typeset code {
68 | color: white !important;
69 | /* box-shadow: 0.29412em 0 0 hsla(0, 0%, 100%, 0.07),
70 | -0.29412em 0 0 hsla(0, 0%, 100%, 0.1);*/
71 | }
72 | .md-typeset a code {
73 | color: #94acff !important;
74 | }
75 | .md-typeset a:hover code {
76 | text-decoration: underline;
77 | }
78 | .linenos {
79 | color: #f5f5f5 !important;
80 | background-color: #313131 !important;
81 | }
82 | .codehilite {
83 | background-color: #44484e !important;
84 | }
85 | .md-typeset .codehilite::-webkit-scrollbar {
86 | height: 1rem !important;
87 | }
88 | .codehilite pre {
89 | color: #fafafa !important;
90 | background-color: transparent !important;
91 | }
92 | .codehilite .hll {
93 | background-color: #272822 !important;
94 | }
95 | .codehilite .c {
96 | color: #8a8f98 !important;
97 | }
98 | .codehilite .err {
99 | color: #960050 !important;
100 | background-color: #1e0010 !important;
101 | }
102 | .codehilite .k {
103 | color: #66d9ef !important;
104 | }
105 | .codehilite .l {
106 | color: #ae81ff !important;
107 | }
108 | .codehilite .n {
109 | color: #f8f8f2 !important;
110 | }
111 | .codehilite .o {
112 | color: #f92672 !important;
113 | }
114 | .codehilite .p {
115 | color: #f8f8f2 !important;
116 | }
117 | .codehilite .cm {
118 | color: #8a8f98 !important;
119 | }
120 | .codehilite .cp {
121 | color: #8a8f98 !important;
122 | }
123 | .codehilite .c1 {
124 | color: #8a8f98 !important;
125 | }
126 | .codehilite .cs {
127 | color: #8a8f98 !important;
128 | }
129 | .codehilite .ge {
130 | font-style: italic !important;
131 | }
132 | .codehilite .gs {
133 | font-weight: bold !important;
134 | }
135 | .codehilite .kc {
136 | color: #66d9ef !important;
137 | }
138 | .codehilite .kd {
139 | color: #66d9ef !important;
140 | }
141 | .codehilite .kn {
142 | color: #f92672 !important;
143 | }
144 | .codehilite .kp {
145 | color: #66d9ef !important;
146 | }
147 | .codehilite .kr {
148 | color: #66d9ef !important;
149 | }
150 | .codehilite .kt {
151 | color: #66d9ef !important;
152 | }
153 | .codehilite .ld {
154 | color: #e6db74 !important;
155 | }
156 | .codehilite .m {
157 | color: #ae81ff !important;
158 | }
159 | .codehilite .s {
160 | color: #e6db74 !important;
161 | }
162 | .codehilite .na {
163 | color: #a6e22e !important;
164 | }
165 | .codehilite .nb {
166 | color: #f8f8f2 !important;
167 | }
168 | .codehilite .nc {
169 | color: #a6e22e !important;
170 | }
171 | .codehilite .no {
172 | color: #66d9ef !important;
173 | }
174 | .codehilite .nd {
175 | color: #a6e22e !important;
176 | }
177 | .codehilite .ni {
178 | color: #f8f8f2 !important;
179 | }
180 | .codehilite .ne {
181 | color: #a6e22e !important;
182 | }
183 | .codehilite .nf {
184 | color: #a6e22e !important;
185 | }
186 | .codehilite .nl {
187 | color: #f8f8f2 !important;
188 | }
189 | .codehilite .nn {
190 | color: #f8f8f2 !important;
191 | }
192 | .codehilite .nx {
193 | color: #a6e22e !important;
194 | }
195 | .codehilite .py {
196 | color: #f8f8f2 !important;
197 | }
198 | .codehilite .nt {
199 | color: #f92672 !important;
200 | }
201 | .codehilite .nv {
202 | color: #f8f8f2 !important;
203 | }
204 | .codehilite .ow {
205 | color: #f92672 !important;
206 | }
207 | .codehilite .w {
208 | color: #f8f8f2 !important;
209 | }
210 | .codehilite .mf {
211 | color: #ae81ff !important;
212 | }
213 | .codehilite .mh {
214 | color: #ae81ff !important;
215 | }
216 | .codehilite .mi {
217 | color: #ae81ff !important;
218 | }
219 | .codehilite .mo {
220 | color: #ae81ff !important;
221 | }
222 | .codehilite .sb {
223 | color: #e6db74 !important;
224 | }
225 | .codehilite .sc {
226 | color: #e6db74 !important;
227 | }
228 | .codehilite .sd {
229 | color: #e6db74 !important;
230 | }
231 | .codehilite .s2 {
232 | color: #e6db74 !important;
233 | }
234 | .codehilite .se {
235 | color: #ae81ff !important;
236 | }
237 | .codehilite .sh {
238 | color: #e6db74 !important;
239 | }
240 | .codehilite .si {
241 | color: #e6db74 !important;
242 | }
243 | .codehilite .sx {
244 | color: #e6db74 !important;
245 | }
246 | .codehilite .sr {
247 | color: #e6db74 !important;
248 | }
249 | .codehilite .s1 {
250 | color: #e6db74 !important;
251 | }
252 | .codehilite .ss {
253 | color: #e6db74 !important;
254 | }
255 | .codehilite .bp {
256 | color: #f8f8f2 !important;
257 | }
258 | .codehilite .vc {
259 | color: #f8f8f2 !important;
260 | }
261 | .codehilite .vg {
262 | color: #f8f8f2 !important;
263 | }
264 | .codehilite .vi {
265 | color: #f8f8f2 !important;
266 | }
267 | .codehilite .il {
268 | color: #ae81ff !important;
269 | }
270 | .codehilite .gu {
271 | color: #8a8f98 !important;
272 | }
273 | .codehilite .gd {
274 | color: #9c1042 !important;
275 | background-color: #eaa;
276 | }
277 | .codehilite .gi {
278 | color: #364c0a !important;
279 | background-color: #91e891;
280 | }
281 | .md-clipboard:before {
282 | color: rgba(255, 255, 255, 0.31);
283 | }
284 | .codehilite:hover .md-clipboard:before, .md-typeset .highlight:hover .md-clipboard:before, pre:hover .md-clipboard:before {
285 | color: rgba(255, 255, 255, 0.6);
286 | }
287 | .md-typeset summary:after {
288 | color: rgba(255, 255, 255, 0.26);
289 | }
290 | .md-typeset .admonition.example > .admonition-title, .md-typeset .admonition.example > summary, .md-typeset details.example > .admonition-title, .md-typeset details.example > summary {
291 | background-color: rgba(154, 109, 255, 0.21);
292 | }
293 | .md-nav__link[data-md-state='blur'] {
294 | color: #aec0ff;
295 | }
296 | .md-typeset .footnote {
297 | color: #888484 !important;
298 | }
299 | .md-typeset .footnote-ref:before {
300 | border-color: #888484 !important;
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/docs_en/css/styles.css:
--------------------------------------------------------------------------------
1 | .text-center {
2 | text-align: center;
3 | }
4 |
5 | article img {
6 | border: 1px solid #eee;
7 | box-shadow: 0 0 1em #ccc;
8 | margin: 30px auto 10px;
9 | }
10 |
11 | article img.emojione {
12 | border: none;
13 | box-shadow: none;
14 | margin: 0;
15 | }
16 |
17 | .md-footer-nav {
18 | background-color: rgba(0,0,0,.57);
19 | }
20 |
21 |
22 | /* Docker Branding */
23 | .md-header {
24 | background-color: #0d9cec !important;
25 | }
26 |
27 | @font-face{
28 | font-family: "Geomanist";
29 | src: url("../fonts/hinted-Geomanist-Book.ttf")
30 | }
31 |
32 | body {
33 | font-family: "Open Sans", sans-serif;
34 | font-size: 15px;
35 | font-weight: normal;
36 | font-style: normal;
37 | font-stretch: normal;
38 | line-height: 1.5;
39 | letter-spacing: normal;
40 | color: #577482;
41 | }
42 |
43 | h1, h2, h3, h4, .md-footer-nav__inner, .md-header-nav__title, footer.md-footer {
44 | font-family: Geomanist;
45 | }
46 |
47 | .md-header-nav__title {
48 | line-height: 2.9rem;
49 | }
50 |
51 | .md-header-nav__button img {
52 | width: 145px;
53 | }
--------------------------------------------------------------------------------
/docs_en/fonts/hinted-Geomanist-Book.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/fonts/hinted-Geomanist-Book.ttf
--------------------------------------------------------------------------------
/docs_en/images/docker-labs-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs_en/images/pwd-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/images/pwd-badge.png
--------------------------------------------------------------------------------
/docs_en/index.md:
--------------------------------------------------------------------------------
1 | redirect: /tutorial/
2 |
3 |
--------------------------------------------------------------------------------
/docs_en/js/custom.js:
--------------------------------------------------------------------------------
1 | $(window).load(function() {
2 | $('body').raptorize({
3 | 'enterOn' : 'konami-code'
4 | });
5 | });
--------------------------------------------------------------------------------
/docs_en/js/jquery.raptorize.1.0.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Raptorize Plugin 1.0
3 | * www.ZURB.com/playground
4 | * Copyright 2010, ZURB
5 | * Free to use under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | */
8 |
9 |
10 | (function($) {
11 |
12 | $.fn.raptorize = function(options) {
13 |
14 | //Yo' defaults
15 | var defaults = {
16 | enterOn: 'click', //timer, konami-code, click
17 | delayTime: 5000 //time before raptor attacks on timer mode
18 | };
19 |
20 | //Extend those options
21 | var options = $.extend(defaults, options);
22 |
23 | return this.each(function() {
24 |
25 | var _this = $(this);
26 | var audioSupported = false;
27 | //Stupid Browser Checking which should be in jQuery Support
28 | if ($.browser.mozilla && $.browser.version.substr(0, 5) >= "1.9.2" || $.browser.webkit) {
29 | audioSupported = true;
30 | }
31 |
32 | //Raptor Vars
33 | var raptorImageMarkup = ''
34 | var raptorAudioMarkup = '';
35 | var locked = false;
36 |
37 | //Append Raptor and Style
38 | $('body').append(raptorImageMarkup);
39 | if(audioSupported) { $('body').append(raptorAudioMarkup); }
40 | var raptor = $('#elRaptor').css({
41 | "position":"fixed",
42 | "bottom": "-700px",
43 | "right" : "0",
44 | "display" : "block"
45 | })
46 |
47 | // Animating Code
48 | function init() {
49 | locked = true;
50 |
51 | //Sound Hilarity
52 | if(audioSupported) {
53 | function playSound() {
54 | document.getElementById('elRaptorShriek').play();
55 | }
56 | playSound();
57 | }
58 |
59 | // Movement Hilarity
60 | raptor.animate({
61 | "bottom" : "0"
62 | }, function() {
63 | $(this).animate({
64 | "bottom" : "-130px"
65 | }, 100, function() {
66 | var offset = (($(this).position().left)+400);
67 | $(this).delay(300).animate({
68 | "right" : offset
69 | }, 2200, function() {
70 | raptor = $('#elRaptor').css({
71 | "bottom": "-700px",
72 | "right" : "0"
73 | })
74 | locked = false;
75 | })
76 | });
77 | });
78 | }
79 |
80 |
81 | //Determine Entrance
82 | if(options.enterOn == 'timer') {
83 | setTimeout(init, options.delayTime);
84 | } else if(options.enterOn == 'click') {
85 | _this.bind('click', function(e) {
86 | e.preventDefault();
87 | if(!locked) {
88 | init();
89 | }
90 | })
91 | } else if(options.enterOn == 'konami-code'){
92 | var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
93 | $(window).bind("keydown.raptorz", function(e){
94 | kkeys.push( e.keyCode );
95 | if ( kkeys.toString().indexOf( konami ) >= 0 ) {
96 | init();
97 | kkeys = [];
98 | // $(window).unbind('keydown.raptorz');
99 | }
100 | }, true);
101 |
102 | }
103 |
104 | });//each call
105 | }//orbit plugin call
106 | })(jQuery);
107 |
108 |
--------------------------------------------------------------------------------
/docs_en/js/raptor-sound.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/js/raptor-sound.mp3
--------------------------------------------------------------------------------
/docs_en/js/raptor-sound.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/js/raptor-sound.ogg
--------------------------------------------------------------------------------
/docs_en/js/raptor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/js/raptor.png
--------------------------------------------------------------------------------
/docs_en/pwd-tips/editor-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/pwd-tips/editor-button.png
--------------------------------------------------------------------------------
/docs_en/pwd-tips/editor-display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/pwd-tips/editor-display.png
--------------------------------------------------------------------------------
/docs_en/pwd-tips/index.md:
--------------------------------------------------------------------------------
1 |
2 | ## Creating Files
3 |
4 | If you're new to a Linux terminal, don't worry! The easiest way to create a file is to use the `touch` command.
5 |
6 | ```bash
7 | touch Dockerfile
8 | ```
9 |
10 | If you run `ls`, you'll see that the file has been created. Once created, you can use the **Editing Files** tips below.
11 |
12 |
13 | ## Editing Files
14 |
15 | In PWD, you are welcome to use any CLI-based editor. However, we know many folks aren't as comfortable in the CLI.
16 | You are welcome to click on the "Editor" button to get a file manager view.
17 |
18 | {: style=width:50% }
19 | {:.text-center}
20 |
21 | After clicking the editor button, the file editor will open. Selecting a file will provide a web-based editor.
22 |
23 | {: style=width:75% }
24 | {: .text-center }
25 |
26 |
27 | ## Opening an App when the badge is gone
28 |
29 | If you have started a container, but the port badge doesn't come up, there is a way to still open the app.
30 |
31 | 1. First, validate the container is actually running and didn't just fail to start. Run `docker ps` and
32 | verify there is a port mapping in the `PORTS` section.
33 |
34 | ```bash
35 | $ docker ps
36 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37 | 976e7066d705 docker-101 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:3000->3000/tcp xenodochial_ritchie
38 | ```
39 |
40 | If the container failed to start, check the container logs and try to figure out what might be going on.
41 |
42 | 1. In PWD, find the `SSH` display. It should have a display that looks like `ssh ip172...`. Copy everything AFTER
43 | the `ssh` portion (`ip172....`).
44 |
45 | 1. Paste that into the web browser, but do NOT hit enter yet. Find the `@` symbol. Replace it with `-PORT.` For example,
46 | if I had `ip172-18-0-22-bmf9t2ds883g009iqq80@direct.labs.play-with-docker.com` and wanted to look at port 3000, I would
47 | open ip172-18-0-22-bmf9t2ds883g009iqq80-3000.direct.labs.play-with-docker.com.
48 |
49 |
--------------------------------------------------------------------------------
/docs_en/tutorial/image-building-best-practices/index.md:
--------------------------------------------------------------------------------
1 |
2 | ## Image Layering
3 |
4 | Did you know that you can look at what makes up an image? Using the `docker image history`
5 | command, you can see the command that was used to create each layer within an image.
6 |
7 | 1. Use the `docker image history` command to see the layers in the `docker-101` image you
8 | created earlier in the tutorial.
9 |
10 | ```bash
11 | docker image history docker-101
12 | ```
13 |
14 | You should get output that looks something like this (dates/IDs may be different).
15 |
16 | ```plaintext
17 | IMAGE CREATED CREATED BY SIZE COMMENT
18 | a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B
19 | f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB
20 | a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB
21 | 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B
22 | b95baba1cfdb 7 weeks ago /bin/sh -c #(nop) CMD ["node"] 0B
23 | 7 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
24 | 7 weeks ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
25 | 7 weeks ago /bin/sh -c apk add --no-cache --virtual .bui… 5.5MB
26 | 7 weeks ago /bin/sh -c #(nop) ENV YARN_VERSION=1.17.3 0B
27 | 7 weeks ago /bin/sh -c addgroup -g 1000 node && addu… 65.4MB
28 | 7 weeks ago /bin/sh -c #(nop) ENV NODE_VERSION=10.16.3 0B
29 | 5 months ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
30 | 5 months ago /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a… 5.53MB
31 | ```
32 |
33 | Each of the lines represents a layer in the image. The display here shows the base at the bottom with
34 | the newest layer at the top. Using this, you can also quickly see the size of each layer, helping
35 | diagnose large images.
36 |
37 | 1. You'll notice that several of the lines are truncated. If you add the `--no-trunc` flag, you'll get the
38 | full output (yes... funny how you use a truncated flag to get untruncated output, huh?)
39 |
40 | ```bash
41 | docker image history --no-trunc docker-101
42 | ```
43 |
44 |
45 | ## Layer Caching
46 |
47 | Now that you've seen the layering in action, there's an important lesson to learn to help decrease build
48 | times for your container images.
49 |
50 | > Once a layer changes, all downstream layers have to be recreated as well
51 |
52 | Let's look at the Dockerfile we were using one more time...
53 |
54 | ```dockerfile
55 | FROM node:10-alpine
56 | WORKDIR /app
57 | COPY . .
58 | RUN yarn install --production
59 | CMD ["node", "/app/src/index.js"]
60 | ```
61 |
62 | Going back to the image history output, we see that each command in the Dockerfile becomes a new layer in the image.
63 | You might remember that when we made a change to the image, the yarn dependencies had to be reinstalled. Is there a
64 | way to fix this? It doesn't make much sense to ship around the same dependencies every time we build, right?
65 |
66 | To fix this, we need to restructure our Dockerfile to help support the caching of the dependencies. For Node-based
67 | applications, those dependencies are defined in the `package.json` file. So, what if we copied only that file in first,
68 | install the dependencies, and _then_ copy in everything else? Then, we only recreate the yarn dependencies if there was
69 | a change to the `package.json`. Make sense?
70 |
71 | 1. Update the Dockerfile to copy in the `package.json` first, install dependencies, and then copy everything else in.
72 |
73 | ```dockerfile hl_lines="3 4 5"
74 | FROM node:10-alpine
75 | WORKDIR /app
76 | COPY package.json yarn.lock ./
77 | RUN yarn install --production
78 | COPY . .
79 | CMD ["node", "/app/src/index.js"]
80 | ```
81 |
82 | 1. Build a new image using `docker build`.
83 |
84 | ```bash
85 | docker build -t docker-101 .
86 | ```
87 |
88 | You should see output like this...
89 |
90 | ```plaintext
91 | Sending build context to Docker daemon 219.1kB
92 | Step 1/6 : FROM node:10-alpine
93 | ---> b95baba1cfdb
94 | Step 2/6 : WORKDIR /app
95 | ---> Using cache
96 | ---> 9577ae713121
97 | Step 3/6 : COPY package* yarn.lock ./
98 | ---> bd5306f49fc8
99 | Step 4/6 : RUN yarn install --production
100 | ---> Running in d53a06c9e4c2
101 | yarn install v1.17.3
102 | [1/4] Resolving packages...
103 | [2/4] Fetching packages...
104 | info fsevents@1.2.9: The platform "linux" is incompatible with this module.
105 | info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation.
106 | [3/4] Linking dependencies...
107 | [4/4] Building fresh packages...
108 | Done in 10.89s.
109 | Removing intermediate container d53a06c9e4c2
110 | ---> 4e68fbc2d704
111 | Step 5/6 : COPY . .
112 | ---> a239a11f68d8
113 | Step 6/6 : CMD ["node", "/app/src/index.js"]
114 | ---> Running in 49999f68df8f
115 | Removing intermediate container 49999f68df8f
116 | ---> e709c03bc597
117 | Successfully built e709c03bc597
118 | Successfully tagged docker-101:latest
119 | ```
120 |
121 | You'll see that all layers were rebuilt. Perfectly fine since we changed the Dockerfile quite a bit.
122 |
123 | 1. Now, make a change to the `src/static/index.html` file (like change the `` to say "The Awesome Todo App").
124 |
125 | 1. Build the Docker image now using `docker build` again. This time, your output should look a little different.
126 |
127 | ```plaintext hl_lines="5 8 11"
128 | Sending build context to Docker daemon 219.1kB
129 | Step 1/6 : FROM node:10-alpine
130 | ---> b95baba1cfdb
131 | Step 2/6 : WORKDIR /app
132 | ---> Using cache
133 | ---> 9577ae713121
134 | Step 3/6 : COPY package* yarn.lock ./
135 | ---> Using cache
136 | ---> bd5306f49fc8
137 | Step 4/6 : RUN yarn install --production
138 | ---> Using cache
139 | ---> 4e68fbc2d704
140 | Step 5/6 : COPY . .
141 | ---> cccde25a3d9a
142 | Step 6/6 : CMD ["node", "/app/src/index.js"]
143 | ---> Running in 2be75662c150
144 | Removing intermediate container 2be75662c150
145 | ---> 458e5c6f080c
146 | Successfully built 458e5c6f080c
147 | Successfully tagged docker-101:latest
148 | ```
149 |
150 | First off, you should notice that the build was MUCH faster! And, you'll see that steps 1-4 all have
151 | `Using cache`. So, hooray! We're using the build cache. Pushing and pulling this image and updates to it
152 | will be much faster as well. Hooray!
153 |
154 |
155 | ## Multi-Stage Builds
156 |
157 | While we're not going to dive into it too much in this tutorial, multi-stage builds are an incredibly powerful
158 | tool to help use multiple stages to create an image. There are several advantages for them:
159 |
160 | - Separate build-time dependencies from runtime dependencies
161 | - Reduce overall image size by shipping _only_ what your app needs to run
162 |
163 | ### Maven/Tomcat Example
164 |
165 | When building Java-based applications, a JDK is needed to compile the source code to Java bytecode. However,
166 | that JDK isn't needed in production. Also, you might be using tools like Maven or Gradle to help build the app.
167 | Those also aren't needed in our final image. Multi-stage builds help.
168 |
169 | ```dockerfile
170 | FROM maven AS build
171 | WORKDIR /app
172 | COPY . .
173 | RUN mvn package
174 |
175 | FROM tomcat
176 | COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
177 | ```
178 |
179 | In this example, we use one stage (called `build`) to perform the actual Java build using Maven. In the second
180 | stage (starting at `FROM tomcat`), we copy in files from the `build` stage. The final image is only the last stage
181 | being created (which can be overridden using the `--target` flag).
182 |
183 |
184 | ### React Example
185 |
186 | When building React applications, we need a Node environment to compile the JS code (typically JSX), SASS stylesheets,
187 | and more into static HTML, JS, and CSS. If we aren't doing server-side rendering, we don't even need a Node environment
188 | for our production build. Why not ship the static resources in a static nginx container?
189 |
190 | ```dockerfile
191 | FROM node:10 AS build
192 | WORKDIR /app
193 | COPY package* yarn.lock ./
194 | RUN yarn install
195 | COPY public ./public
196 | COPY src ./src
197 | RUN yarn run build
198 |
199 | FROM nginx:alpine
200 | COPY --from=build /app/build /usr/share/nginx/html
201 | ```
202 |
203 | Here, we are using a `node:10` image to perform the build (maximizing layer caching) and then copying the output
204 | into an nginx container. Cool, huh?
205 |
206 |
207 | ## Recap
208 |
209 | By understanding a little bit about how images are structured, we can build images faster and ship fewer changes.
210 | Multi-stage builds also help us reduce overall image size and increase final container security by separating
211 | build-time dependencies from runtime dependencies.
212 |
213 |
--------------------------------------------------------------------------------
/docs_en/tutorial/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | next_page: app.md
3 | ---
4 |
5 | ## The command you just ran
6 |
7 | Congratulations! You have started the container for this tutorial!
8 | Let's first explain the command that you just ran. In case you forgot,
9 | here's the command:
10 |
11 | ```cli
12 | docker run -d -p 80:80 dockersamples/101-tutorial
13 | ```
14 |
15 | You'll notice a few flags being used. Here's some more info on them:
16 |
17 | - `-d` - run the container in detached mode (in the background)
18 | - `-p 80:80` - map port 80 of the host to port 80 in the container
19 | - `dockersamples/101-tutorial` - the image to use
20 |
21 | !!! info "Pro tip"
22 | You can combine single character flags to shorten the full command.
23 | As an example, the command above could be written as:
24 | ```
25 | docker run -dp 80:80 dockersamples/101-tutorial
26 | ```
27 |
28 | ## What is a container?
29 |
30 | Now that you've run a container, what _is_ a container? Simply put, a container is
31 | simply another process on your machine that has been isolated from all other processes
32 | on the host machine. That isolation leverages [kernel namespaces and cgroups](https://medium.com/@saschagrunert/demystifying-containers-part-i-kernel-space-2c53d6979504), features that have been
33 | in Linux for a long time. Docker has worked to make these capabilities approachable and easy to use.
34 |
35 | !!! info "Creating Containers from Scratch"
36 | If you'd like to see how containers are built from scratch, Liz Rice from Aqua Security
37 | has a fantastic talk in which she creates a container from scratch in Go. While she makes
38 | a simple container, this talk doesn't go into networking, using images for the filesystem,
39 | and more. But, it gives a _fantastic_ deep dive into how things are working.
40 |
41 |
42 |
43 | ## What is a container image?
44 |
45 | When running a container, it uses an isolated filesystem. This custom filesystem is provided
46 | by a **container image**. Since the image contains the container's filesystem, it must contain everything
47 | needed to run an application - all dependencies, configuration, scripts, binaries, etc. The
48 | image also contains other configuration for the container, such as environment variables,
49 | a default command to run, and other metadata.
50 |
51 | We'll dive deeper into images later on, covering topics such as layering, best practices, and more.
52 |
53 | !!! info
54 | If you're familiar with `chroot`, think of a container as extended version of `chroot`. The
55 | filesystem is simply coming from the image. But, a container adds additional isolation not
56 | available when simply using chroot.
57 |
58 |
--------------------------------------------------------------------------------
/docs_en/tutorial/multi-container-apps/multi-app-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/multi-container-apps/multi-app-architecture.png
--------------------------------------------------------------------------------
/docs_en/tutorial/our-application/index.md:
--------------------------------------------------------------------------------
1 |
2 | For the rest of this tutorial, we will be working with a simple todo
3 | list manager that is running in Node. If you're not familiar with Node,
4 | don't worry! No real JavaScript experience is needed!
5 |
6 | At this point, your development team is quite small and you're simply
7 | building an app to prove out your MVP (minimum viable product). You want
8 | to show how it works and what it's capable of doing without needing to
9 | think about how it will work for a large team, multiple developers, etc.
10 |
11 | {: style="width:50%;" }
12 | { .text-center }
13 |
14 |
15 | ## Getting our App into PWD
16 |
17 | Before we can run the application, we need to get the application source code into
18 | the Play with Docker environment. For real projects, you can clone the repo. But, in
19 | this case, you will upload a ZIP archive.
20 |
21 | 1. [Download the zip](/assets/app.zip) and upload it to Play with Docker. As a
22 | tip, you can drag and drop the zip (or any other file) on to the terminal in PWD.
23 |
24 | 1. In the PWD terminal, extract the zip file.
25 |
26 | ```bash
27 | unzip app.zip
28 | ```
29 |
30 | 1. Change your current working directory into the new 'app' folder.
31 |
32 | ```bash
33 | cd app/
34 | ```
35 |
36 | 1. In this directory, you should see a simple Node-based application.
37 |
38 | ```bash
39 | ls
40 | package.json spec src yarn.lock
41 | ```
42 |
43 |
44 | ## Building the App's Container Image
45 |
46 | In order to build the application, we need to use a `Dockerfile`. A
47 | Dockerfile is simply a text-based script of instructions that is used to
48 | create a container image. If you've created Dockerfiles before, you might
49 | see a few flaws in the Dockerfile below. But, don't worry! We'll go over them.
50 |
51 | 1. Create a file named Dockerfile with the following contents.
52 |
53 | ```dockerfile
54 | FROM node:10-alpine
55 | WORKDIR /app
56 | COPY . .
57 | RUN yarn install --production
58 | CMD ["node", "/app/src/index.js"]
59 | ```
60 |
61 | 1. Build the container image using the `docker build` command.
62 |
63 | ```bash
64 | docker build -t docker-101 .
65 | ```
66 |
67 | This command used the Dockerfile to build a new container image. You might
68 | have noticed that a lot of "layers" were downloaded. This is because we instructed
69 | the builder that we wanted to start from the `node:10-alpine` image. But, since we
70 | didn't have that on our machine, that image needed to be downloaded.
71 |
72 | After that, we copied in our application and used `yarn` to install our application's
73 | dependencies. The `CMD` directive specifies the default command to run when starting
74 | a container from this image.
75 |
76 |
77 | ## Starting an App Container
78 |
79 | Now that we have an image, let's run the application! To do so, we will use the `docker run`
80 | command (remember that from earlier?).
81 |
82 | 1. Start your container using the `docker run` command:
83 |
84 | ```bash
85 | docker run -dp 3000:3000 docker-101
86 | ```
87 |
88 | Remember the `-d` and `-p` flags? We're running the new container in "detached" mode (in the
89 | background) and creating a mapping between the host's port 3000 to the container's port 3000.
90 |
91 | 1. Open the application by clicking on the "3000" badge at the top of the PWD interface. Once open,
92 | you should have an empty todo list!
93 |
94 | {: style="width:450px;margin-top:20px;"}
95 | {: .text-center }
96 |
97 | 1. Go ahead and add an item or two and see that it works as you expect. You can mark items as
98 | complete and remove items.
99 |
100 |
101 | At this point, you should have a running todo list manager with a few items, all built by you!
102 | Now, let's make a few changes and learn about managing our containers.
103 |
104 |
105 | ## Recap
106 |
107 | In this short section, we learned the very basics about building a container image and created a
108 | Dockerfile to do so. Once we built an image, we started the container and saw the running app!
109 |
110 | Next, we're going to make a modification to our app and learn how to update our running application
111 | with a new image. Along the way, we'll learn a few other useful commands.
112 |
--------------------------------------------------------------------------------
/docs_en/tutorial/our-application/todo-list-empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/our-application/todo-list-empty.png
--------------------------------------------------------------------------------
/docs_en/tutorial/our-application/todo-list-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/our-application/todo-list-sample.png
--------------------------------------------------------------------------------
/docs_en/tutorial/persisting-our-data/index.md:
--------------------------------------------------------------------------------
1 |
2 | In case you didn't notice, our todo list is being wiped clean every single time
3 | we launch the container. Why is this? Let's dive into how the container is working.
4 |
5 | ## The Container's Filesystem
6 |
7 | When a container runs, it uses the various layers from an image for its filesystem.
8 | Each container also gets its own "scratch space" to create/update/remove files. Any
9 | changes won't be seen in another container, _even if_ they are using the same image.
10 |
11 |
12 | ### Seeing this in Practice
13 |
14 | To see this in action, we're going to start two containers and create a file in each.
15 | What you'll see is that the files created in one container aren't available in another.
16 |
17 | 1. Start a `ubuntu` container that will create a file named `/data.txt` with a random number
18 | between 1 and 10000.
19 |
20 | ```bash
21 | docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
22 | ```
23 |
24 | In case you're wondering about the command, we're starting a bash shell and invoking two
25 | commands (why we have the `&&`). The first portion picks a single random number and writes
26 | it to `/data.txt`. The second command is simply watching a file to keep the container running.
27 |
28 | 1. Validate we can see the output by `exec`'ing into the container. To do so, you need to get the
29 | container's ID (use `docker ps` to get it).
30 |
31 | ```bash
32 | docker exec cat /data.txt
33 | ```
34 |
35 | You should see a random number!
36 |
37 | 1. Now, let's start another `ubuntu` container (the same image) and we'll see we don't have the same
38 | file.
39 |
40 | ```bash
41 | docker run -it ubuntu ls /
42 | ```
43 |
44 | And look! There's no `data.txt` file there! That's because it was written to the scratch space for
45 | only the first container.
46 |
47 | 1. Go ahead and remove the first container using the `docker rm -f` command.
48 |
49 |
50 | ## Container Volumes
51 |
52 | With the previous experiment, we saw that each container restarts from scratch from its image. While containers
53 | can create, update, and delete files, those changes are lost when the container is removed and are isolated
54 | to that container. With volumes, we can change all of this.
55 |
56 | [Volumes](https://docs.docker.com/storage/volumes/) provide the ability to connect specific filesystem paths of
57 | the container back to the host machine. If a directory in the container is mounted, changes in that
58 | directory are also seen on the host machine. If we mount that same directory across container restarts, we'd see
59 | the same files.
60 |
61 | There are two main types of volumes. We will eventually use both, but we will start with **named volumes**.
62 |
63 |
64 |
65 | ## Persisting our Todo Data
66 |
67 | By default, the todo app stores its data in a [SQLite Database](https://www.sqlite.org/index.html) at
68 | `/etc/todos/todo.db`. If you're not familiar with SQLite, no worries! It's simply a relational database in
69 | which all of the data is stored in a single file. While this isn't the best for large-scale applications,
70 | it works for small demos. We'll talk about switching this to an actual database engine later.
71 |
72 | With the database being a single file, if we can persist that file on the host and make it available to the
73 | next container, it should be able to pick up where the last one left off. By creating a volume and attaching
74 | (often called "mounting") it to the directory the data is stored in, we can persist the data. As our container
75 | writes to the `todo.db` file, it will be persisted to the host in the volume.
76 |
77 | As mentioned, we are going to use a **named volume**. Think of a named volume as simply a bucket of data.
78 | Docker maintains the physical location on the disk and you only need to remember the name of the volume.
79 | Every time you use the volume, Docker will make sure the correct data is provided.
80 |
81 | 1. Create a volume by using the `docker volume create` command.
82 |
83 | ```bash
84 | docker volume create todo-db
85 | ```
86 |
87 | 1. Start the todo container, but add the `-v` flag to specify a volume mount. We will use the named volume and mount
88 | it to `/etc/todos`, which will capture all files created at the path.
89 |
90 | ```bash
91 | docker run -dp 3000:3000 -v todo-db:/etc/todos docker-101
92 | ```
93 |
94 | 1. Once the container starts up, open the app and add a few items to your todo list.
95 |
96 | {: style="width: 55%; " }
97 | {: .text-center }
98 |
99 | 1. Remove the container for the todo app. Use `docker ps` to get the ID and then `docker rm -f ` to remove it.
100 |
101 | 1. Start a new container using the same command from above.
102 |
103 | 1. Open the app. You should see your items still in your list!
104 |
105 | 1. Go ahead and remove the container when you're done checking out your list.
106 |
107 | Hooray! You've now learned how to persist data!
108 |
109 | !!! info "Pro-tip"
110 | While named volumes and bind mounts (which we'll talk about in a minute) are the two main types of volumes supported
111 | by a default Docker engine installation, there are many volume driver plugins available to support NFS, SFTP, NetApp,
112 | and more! This will be especially important once you start running containers on multiple hosts in a clustered
113 | environment with Swarm, Kubernetes, etc.
114 |
115 |
116 | ## Diving into our Volume
117 |
118 | A lot of people frequently ask "Where is Docker _actually_ storing my data when I use a named volume?" If you want to know,
119 | you can use the `docker volume inspect` command.
120 |
121 | ```bash
122 | docker volume inspect todo-db
123 | [
124 | {
125 | "CreatedAt": "2019-09-26T02:18:36Z",
126 | "Driver": "local",
127 | "Labels": {},
128 | "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
129 | "Name": "todo-db",
130 | "Options": {},
131 | "Scope": "local"
132 | }
133 | ]
134 | ```
135 |
136 | The `Mountpoint` is the actual location on the disk where the data is stored. Note that on most machines, you will
137 | need to have root access to access this directory from the host. But, that's where it is!
138 |
139 |
140 | ## Recap
141 |
142 | At this point, we have a functioning application that can survive restarts! We can show it off to our investors and
143 | hope they can catch our vision!
144 |
145 | However, we saw earlier that rebuilding images for every change takes quite a bit of time. There's got to be a better
146 | way to make changes, right? With bind mounts (which we hinted at earlier), there is a better way! Let's take a look at
147 | that now!
148 |
--------------------------------------------------------------------------------
/docs_en/tutorial/persisting-our-data/items-added.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/persisting-our-data/items-added.png
--------------------------------------------------------------------------------
/docs_en/tutorial/sharing-our-app/index.md:
--------------------------------------------------------------------------------
1 |
2 | Now that we've built an image, let's share it! To share Docker images, you have to use a Docker
3 | registry. The default registry is Docker Hub and is where all of the images we've used have come from.
4 |
5 | ## Create a Repo
6 |
7 | To push an image, we first need to create a repo on Docker Hub.
8 |
9 | 1. Go to [Docker Hub](https://hub.docker.com) and log in if you need to.
10 |
11 | 1. Click the **Create Repository** button.
12 |
13 | 1. For the repo name, use `101-todo-app`. Make sure the Visibility is `Public`.
14 |
15 | 1. Click the **Create** button!
16 |
17 | If you look on the right-side of the page, you'll see a section named **Docker commands**. This gives
18 | an example command that you will need to run to push to this repo.
19 |
20 | {: style=width:75% }
21 | {: .text-center }
22 |
23 |
24 | ## Pushing our Image
25 |
26 | 1. Back in your PWD instance, try running the command. You should get an error that looks something
27 | like this:
28 |
29 | ```plaintext
30 | $ docker push dockersamples/101-todo-app
31 | The push refers to repository [docker.io/dockersamples/101-todo-app]
32 | An image does not exist locally with the tag: dockersamples/101-todo-app
33 | ```
34 |
35 | Why did it fail? The push command was looking for an image named dockersamples/101-todo-app, but
36 | didn't find one. If you run `docker image ls`, you won't see one either.
37 |
38 | To fix this, we need to "tag" our image, which basically means give it another name.
39 |
40 | 1. Login to the Docker Hub using the command `docker login -u YOUR-USER-NAME`.
41 |
42 | 1. Use the `docker tag` command to give the `docker-101` image a new name. Be sure to swap out
43 | `YOUR-USER-NAME` with your Docker ID.
44 |
45 | ```bash
46 | docker tag docker-101 YOUR-USER-NAME/101-todo-app
47 | ```
48 |
49 | 1. Now try your push command again. If you're copying the value from Docker Hub, you can drop the
50 | `tagname` portion, as we didn't add a tag to the image name.
51 |
52 | ```bash
53 | docker push YOUR-USER-NAME/101-todo-app
54 | ```
55 |
56 | ## Running our Image on a New Instance
57 |
58 | Now that our image has been built and pushed into a registry, let's try running our app on a brand
59 | instance that has never seen this container!
60 |
61 | 1. Back in PWD, click on **Add New Instance** to create a new instance.
62 |
63 | 1. In the new instance, start your freshly pushed app.
64 |
65 | ```bash
66 | docker run -dp 3000:3000 YOUR-USER-NAME/101-todo-app
67 | ```
68 |
69 | You should see the image get pulled down and eventually start up!
70 |
71 | 1. Click on the 3000 badge when it comes up and you should see the app with your modifications! Hooray!
72 |
73 |
74 | ## Recap
75 |
76 | In this section, we learned how to share our images by pushing them to a registry. We then went to a
77 | brand new instance and were able to run the freshly pushed image. This is quite common in CI pipelines,
78 | where the pipeline will create the image and push it to a registry and then the production environment
79 | can use the latest version of the image.
80 |
81 | Now that we have that figured out, let's circle back around to what we noticed at the end of the last
82 | section. As a reminder, we noticed that when we restarted the app, we lost all of our todo list items.
83 | That's obviously not a great user experience, so let's learn how we can persist the data across
84 | restarts!
--------------------------------------------------------------------------------
/docs_en/tutorial/sharing-our-app/push-command.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/sharing-our-app/push-command.png
--------------------------------------------------------------------------------
/docs_en/tutorial/updating-our-app/index.md:
--------------------------------------------------------------------------------
1 |
2 | As a small feature request, we've been asked by the product team to
3 | change the "empty text" when we don't have any todo list items. They
4 | would like to transition it to the following:
5 |
6 | > You have no todo items yet! Add one above!
7 |
8 | Pretty simple, right? Let's make the change.
9 |
10 | ## Updating our Source Code
11 |
12 | 1. In the `~/app/src/static/js/app.js` file, update line 56 to use the new empty text. ([Editing files in PWD tips here](/pwd-tips#editing-files))
13 |
14 | ```diff
15 | -
No items yet! Add one above!
16 | +
You have no todo items yet! Add one above!
17 | ```
18 |
19 | 1. Let's build our updated version of the image, using the same command we used before.
20 |
21 | ```bash
22 | docker build -t docker-101 .
23 | ```
24 |
25 | 1. Let's start a new container using the updated code.
26 |
27 | ```bash
28 | docker run -dp 3000:3000 docker-101
29 | ```
30 |
31 | **Uh oh!** You probably saw an error like this (the IDs will be different):
32 |
33 | ```bash
34 | docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell
35 | (bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind for 0.0.0.0:3000 failed: port is already allocated.
36 | ```
37 |
38 | So, what happened? We aren't able to start the new container because our old container is still
39 | running. The reason this is a problem is because that container is using the host's port 3000 and
40 | only one process (containers included) can listen to a specific port. To fix this, we need to remove
41 | the old container.
42 |
43 |
44 | ## Replacing our Old Container
45 |
46 | To remove a container, it first needs to be stopped. Then, it can be removed.
47 |
48 | 1. Get the ID of the container by using the `docker ps` command.
49 |
50 | ```bash
51 | docker ps
52 | ```
53 |
54 | 1. Use the `docker stop` command to stop the container.
55 |
56 | ```bash
57 | # Swap out with the ID from docker ps
58 | docker stop
59 | ```
60 |
61 | 1. Once the container has stopped, you can remove it by using the `docker rm` command.
62 |
63 | ```bash
64 | docker rm
65 | ```
66 |
67 | 1. Now, start your updated app.
68 |
69 | ```bash
70 | docker run -dp 3000:3000 docker-101
71 | ```
72 |
73 | 1. Open the app and you should see your updated help text!
74 |
75 | {: style="width:55%" }
76 | {: .text-center }
77 |
78 | !!! info "Pro tip"
79 | You can stop and remove a container in a single command by adding the "force" flag
80 | to the `docker rm` command. For example: `docker rm -f `
81 |
82 |
83 | ## Recap
84 |
85 | While we were able to build an update, there were two things you might have noticed:
86 |
87 | - All of the existing items in our todo list are gone! That's not a very good app! We'll talk about that
88 | shortly.
89 | - There were _a lot_ of steps involved for such a small change. In an upcoming section, we'll talk about
90 | how to see code updates without needing to rebuild and start a new container every time we make a change.
91 |
92 | Before talking about persistence, we'll quickly see how to share these images with others.
93 |
--------------------------------------------------------------------------------
/docs_en/tutorial/updating-our-app/todo-list-updated-empty-text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/updating-our-app/todo-list-updated-empty-text.png
--------------------------------------------------------------------------------
/docs_en/tutorial/using-bind-mounts/index.md:
--------------------------------------------------------------------------------
1 |
2 | In the previous chapter, we talked about and used a **named volume** to persist the data in our database.
3 | Named volumes are great if we simply want to store data, as we don't have to worry about _where_ the data
4 | is stored.
5 |
6 | With **bind mounts**, we control the exact mountpoint on the host. We can use this to persist data, but is often
7 | used to provide additional data into containers. When working on an application, we can use a bind mount to
8 | mount our source code into the container to let it see code changes, respond, and let us see the changes right
9 | away.
10 |
11 | For Node-based applications, [nodemon](https://npmjs.com/package/nodemon) is a great tool to watch for file
12 | changes and then restart the application. There are equivalent tools in most other languages and frameworks.
13 |
14 | ## Quick Volume Type Comparisons
15 |
16 | Bind mounts and named volumes are the two main types of volumes that come with the Docker engine. However, additional
17 | volume drivers are available to support other uses cases ([SFTP](https://github.com/vieux/docker-volume-sshfs), [Ceph](https://ceph.com/geen-categorie/getting-started-with-the-docker-rbd-volume-plugin/), [NetApp](https://netappdvp.readthedocs.io/en/stable/), [S3](https://github.com/elementar/docker-s3-volume), and more).
18 |
19 | | | Named Volumes | Bind Mounts |
20 | | - | ------------- | ----------- |
21 | | Host Location | Docker chooses | You control |
22 | | Mount Example (using `-v`) | my-volume:/usr/local/data | /path/to/data:/usr/local/data |
23 | | Populates new volume with container contents | Yes | No |
24 | | Supports Volume Drivers | Yes | No |
25 |
26 |
27 | ## Starting a Dev-Mode Container
28 |
29 | To run our container to support a development workflow, we will do the following:
30 |
31 | - Mount our source code into the container
32 | - Install all dependencies, including the "dev" dependencies
33 | - Start nodemon to watch for filesystem changes
34 |
35 | So, let's do it!
36 |
37 | 1. Make sure you don't have any previous `docker-101` containers running.
38 |
39 | 1. Run the following command. We'll explain what's going on afterwards:
40 |
41 | ```bash
42 | docker run -dp 3000:3000 \
43 | -w /app -v $PWD:/app \
44 | node:10-alpine \
45 | sh -c "yarn install && yarn run dev"
46 | ```
47 |
48 | - `-dp 3000:3000` - same as before. Run in detached (background) mode and create a port mapping
49 | - `-w /app` - sets the "working directory" or the current directory that the command will run from
50 | - `node:10-alpine` - the image to use. Note that this is the base image for our app from the Dockerfile
51 | - `sh -c "yarn install && yarn run dev"` - the command. We're starting a shell using `sh` (alpine doesn't have `bash`) and
52 | running `yarn install` to install _all_ dependencies and then running `yarn run dev`. If we look in the `package.json`,
53 | we'll see that the `dev` script is starting `nodemon`.
54 |
55 | 1. You can watch the logs using `docker logs -f `. You'll know you're ready to go when you see this...
56 |
57 | ```bash
58 | docker logs -f
59 | $ nodemon src/index.js
60 | [nodemon] 1.19.2
61 | [nodemon] to restart at any time, enter `rs`
62 | [nodemon] watching dir(s): *.*
63 | [nodemon] starting `node src/index.js`
64 | Using sqlite database at /etc/todos/todo.db
65 | Listening on port 3000
66 | ```
67 |
68 | When you're done watching the logs, exit out by hitting `Ctrl`+`C`.
69 |
70 | 1. Now, let's make a change to the app. In the `src/static/js/app.js` file, let's change the "Add Item" button to simply say
71 | "Add". This change will be on line 109.
72 |
73 | ```diff
74 | - {submitting ? 'Adding...' : 'Add Item'}
75 | + {submitting ? 'Adding...' : 'Add'}
76 | ```
77 |
78 | 1. Simply refresh the page (or open it) and you should see the change reflected in the browser almost immediately. It might
79 | take a few seconds for the Node server to restart, so if you get an error, just try refreshing after a few seconds.
80 |
81 | {: style="width:75%;"}
82 | {: .text-center }
83 |
84 | 1. Feel free to make any other changes you'd like to make. When you're done, stop the container and build your new image
85 | using `docker build -t docker-101 .`.
86 |
87 |
88 | Using bind mounts is _very_ common for local development setups. The advantage is that the dev machine doesn't need to have
89 | all of the build tools and environments installed. With a single `docker run` command, the dev environment is pulled and ready
90 | to go. We'll talk about Docker Compose in a future step, as this will help simplify our commands (we're already getting a lot
91 | of flags).
92 |
93 | ## Recap
94 |
95 | At this point, we can persist our database and respond rapidly to the needs and demands of our investors and founders. Hooray!
96 | But, guess what? We received great news!
97 |
98 | **Your project has been selected for future development!**
99 |
100 | In order to prepare for production, we need to migrate our database from working in SQLite to something that can scale a
101 | little better. For simplicity, we'll keep with a relational database and switch our application to use MySQL. But, how
102 | should we run MySQL? How do we allow the containers to talk to each other? We'll talk about that next!
103 |
--------------------------------------------------------------------------------
/docs_en/tutorial/using-bind-mounts/updated-add-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_en/tutorial/using-bind-mounts/updated-add-button.png
--------------------------------------------------------------------------------
/docs_en/tutorial/what-next/index.md:
--------------------------------------------------------------------------------
1 |
2 | Although we're done with our workshop, there's still a LOT more to learn about containers!
3 | We're not going to go deep-dive here, but here are a few other areas to look at next!
4 |
5 | ## Container Orchestration
6 |
7 | Running containers in production is tough. You don't want to log into a machine and simply run a
8 | `docker run` or `docker-compose up`. Why not? Well, what happens if the containers die? How do you
9 | scale across several machines? Container orchestration solves this problem. Tools like Kubernetes,
10 | Swarm, Nomad, and ECS all help solve this problem, all in slightly different ways.
11 |
12 | The general idea is that you have "managers" who receive **expected state**. This state might be
13 | "I want to run two instances of my web app and expose port 80." The managers then look at all of the
14 | machines in the cluster and delegate work to "worker" nodes. The managers watch for changes (such as
15 | a container quitting) and then work to make **actual state** reflect the expected state.
16 |
17 |
18 | ## Cloud Native Computing Foundation Projects
19 |
20 | The CNCF is a vendor-neutral home for various open-source projects, including Kubernetes, Prometheus,
21 | Envoy, Linkerd, NATS, and more! You can view the [graduated and incubated projects here](https://www.cncf.io/projects/)
22 | and the entire [CNCF Landscape here](https://landscape.cncf.io/). There are a LOT of projects to help
23 | solve problems around monitoring, logging, security, image registries, messaging, and more!
24 |
25 | So, if you're new to the container landscape and cloud-native application development, welcome! Please
26 | connect to the community, ask questions, and keep learning! We're excited to have you!
27 |
--------------------------------------------------------------------------------
/docs_es/consejos-para-usar-pwd/editor-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/consejos-para-usar-pwd/editor-button.png
--------------------------------------------------------------------------------
/docs_es/consejos-para-usar-pwd/editor-display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/consejos-para-usar-pwd/editor-display.png
--------------------------------------------------------------------------------
/docs_es/consejos-para-usar-pwd/index.md:
--------------------------------------------------------------------------------
1 |
2 | ## Creación de archivos
3 |
4 | Si usted es nuevo en una terminal Linux, no se preocupe! La forma más fácil de crear un archivo es usar el comando `touch`.
5 |
6 | ```bash
7 | touch Dockerfile
8 | ```
9 |
10 | Si ejecuta `ls`, verá que el archivo ha sido creado. Una vez creado, puede utilizar los siguientes consejos de **Edición de archivos**.
11 |
12 |
13 | ## Edición de archivos
14 |
15 | En PWD, puede utilizar cualquier editor basado en CLI. Sin embargo, sabemos que mucha gente no se siente tan cómoda en el CLI. Puede hacer clic en el botón "Editor" para obtener una vista del administrador de archivos.
16 |
17 | {: style=width:50% }
18 | {:.text-center}
19 |
20 | Después de hacer clic en el botón del editor, se abrirá el editor de archivos. La selección de un archivo proporcionará un editor basado en la web.
21 |
22 | {: style=width:75% }
23 | {: .text-center }
24 |
25 |
26 | ## Abrir una aplicación cuando la insignia se ha ido
27 |
28 | Si ha iniciado un contenedor, pero no aparece la insignia de puerto, existe una forma de abrir la aplicación.
29 |
30 | 1. En primer lugar, valida que el contenedor se está ejecutando y que no ha fallado al arrancar. Ejecute `docker ps` y compruebe que hay una asignación de puertos en la sección `PORTS`.
31 |
32 | ```bash
33 | $ docker ps
34 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
35 | 976e7066d705 docker-101 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:3000->3000/tcp xenodochial_ritchie
36 | ```
37 |
38 | Si el contenedor no se inició, revise los registros del contenedor y trate de averiguar qué podría estar pasando.
39 |
40 | 1. En PWD, busque la pantalla `SSH`. Debería tener una pantalla que se parezca a `ssh ip172....`. Copia todo DESPUÉS de la parte `ssh` (`ip172.....`).
41 |
42 | 1. Pegue eso en el navegador web, pero NO presione enter todavía. Encuentra el símbolo `@`. Sustitúyalo por `-PORT.` Por ejemplo, si yo tuviera `ip172-18-0-22-bmf9t2ds883g009iqq80@direct.labs.play-with-docker.com` y quería ver el puerto 3000, debería abrir ip172-18-0-22-bmf9t2ds883g009iqq80-3000.direct.labs.play-with-docker.com.
43 |
44 |
--------------------------------------------------------------------------------
/docs_es/css/dark-mode.css:
--------------------------------------------------------------------------------
1 | @media (prefers-color-scheme: dark) {
2 | .md-main {
3 | color: rgba(255, 255, 255, 0.75) !important;
4 | background-color: #36393e !important;
5 | }
6 |
7 | article img {
8 | box-shadow: 0 0 1em #000;
9 | }
10 |
11 | .md-main h1 {
12 | color: rgba(255, 255, 255, 0.8) !important;
13 | }
14 | blockquote {
15 | color: rgba(255, 255, 255, 0.75) !important;
16 | }
17 | table {
18 | background-color: #616161 !important;
19 | }
20 | tbody {
21 | background-color: #484848 !important;
22 | }
23 | .md-sidebar__scrollwrap::-webkit-scrollbar-thumb {
24 | background-color: #e0e0e0 !important;
25 | }
26 | .md-nav {
27 | color: rgba(255, 255, 255, 0.8) !important;
28 | background-color: #36393e !important;
29 | }
30 | html .md-nav--primary .md-nav__title:before {
31 | color: #fafafa !important;
32 | }
33 | .md-nav__title {
34 | color: rgba(255, 255, 255, 0.9) !important;
35 | background-color: #36393e !important;
36 | }
37 | .md-nav--primary .md-nav__link:after {
38 | color: #fafafa !important;
39 | }
40 | .md-nav__list {
41 | color: rgba(255, 255, 255, 0.8) !important;
42 | background-color: #36393e !important;
43 | }
44 | .md-nav__item {
45 | color: rgba(255, 255, 255, 0.7) !important;
46 | background-color: #36393e !important;
47 | }
48 | .md-search__scrollwrap::-webkit-scrollbar-thumb {
49 | background-color: #e0e0e0 !important;
50 | }
51 | .md-search__scrollwrap {
52 | background-color: #44484e !important;
53 | }
54 | .md-search-result__article--document:before {
55 | color: #eee !important;
56 | }
57 | .md-search-result__list {
58 | color: #eee !important;
59 | background-color: #36393e !important;
60 | }
61 | .md-search-result__meta {
62 | background-color: #eee !important;
63 | }
64 | .md-search-result__teaser {
65 | color: #bdbdbd !important;
66 | }
67 | .md-typeset code {
68 | color: white !important;
69 | /* box-shadow: 0.29412em 0 0 hsla(0, 0%, 100%, 0.07),
70 | -0.29412em 0 0 hsla(0, 0%, 100%, 0.1);*/
71 | }
72 | .md-typeset a code {
73 | color: #94acff !important;
74 | }
75 | .md-typeset a:hover code {
76 | text-decoration: underline;
77 | }
78 | .linenos {
79 | color: #f5f5f5 !important;
80 | background-color: #313131 !important;
81 | }
82 | .codehilite {
83 | background-color: #44484e !important;
84 | }
85 | .md-typeset .codehilite::-webkit-scrollbar {
86 | height: 1rem !important;
87 | }
88 | .codehilite pre {
89 | color: #fafafa !important;
90 | background-color: transparent !important;
91 | }
92 | .codehilite .hll {
93 | background-color: #272822 !important;
94 | }
95 | .codehilite .c {
96 | color: #8a8f98 !important;
97 | }
98 | .codehilite .err {
99 | color: #960050 !important;
100 | background-color: #1e0010 !important;
101 | }
102 | .codehilite .k {
103 | color: #66d9ef !important;
104 | }
105 | .codehilite .l {
106 | color: #ae81ff !important;
107 | }
108 | .codehilite .n {
109 | color: #f8f8f2 !important;
110 | }
111 | .codehilite .o {
112 | color: #f92672 !important;
113 | }
114 | .codehilite .p {
115 | color: #f8f8f2 !important;
116 | }
117 | .codehilite .cm {
118 | color: #8a8f98 !important;
119 | }
120 | .codehilite .cp {
121 | color: #8a8f98 !important;
122 | }
123 | .codehilite .c1 {
124 | color: #8a8f98 !important;
125 | }
126 | .codehilite .cs {
127 | color: #8a8f98 !important;
128 | }
129 | .codehilite .ge {
130 | font-style: italic !important;
131 | }
132 | .codehilite .gs {
133 | font-weight: bold !important;
134 | }
135 | .codehilite .kc {
136 | color: #66d9ef !important;
137 | }
138 | .codehilite .kd {
139 | color: #66d9ef !important;
140 | }
141 | .codehilite .kn {
142 | color: #f92672 !important;
143 | }
144 | .codehilite .kp {
145 | color: #66d9ef !important;
146 | }
147 | .codehilite .kr {
148 | color: #66d9ef !important;
149 | }
150 | .codehilite .kt {
151 | color: #66d9ef !important;
152 | }
153 | .codehilite .ld {
154 | color: #e6db74 !important;
155 | }
156 | .codehilite .m {
157 | color: #ae81ff !important;
158 | }
159 | .codehilite .s {
160 | color: #e6db74 !important;
161 | }
162 | .codehilite .na {
163 | color: #a6e22e !important;
164 | }
165 | .codehilite .nb {
166 | color: #f8f8f2 !important;
167 | }
168 | .codehilite .nc {
169 | color: #a6e22e !important;
170 | }
171 | .codehilite .no {
172 | color: #66d9ef !important;
173 | }
174 | .codehilite .nd {
175 | color: #a6e22e !important;
176 | }
177 | .codehilite .ni {
178 | color: #f8f8f2 !important;
179 | }
180 | .codehilite .ne {
181 | color: #a6e22e !important;
182 | }
183 | .codehilite .nf {
184 | color: #a6e22e !important;
185 | }
186 | .codehilite .nl {
187 | color: #f8f8f2 !important;
188 | }
189 | .codehilite .nn {
190 | color: #f8f8f2 !important;
191 | }
192 | .codehilite .nx {
193 | color: #a6e22e !important;
194 | }
195 | .codehilite .py {
196 | color: #f8f8f2 !important;
197 | }
198 | .codehilite .nt {
199 | color: #f92672 !important;
200 | }
201 | .codehilite .nv {
202 | color: #f8f8f2 !important;
203 | }
204 | .codehilite .ow {
205 | color: #f92672 !important;
206 | }
207 | .codehilite .w {
208 | color: #f8f8f2 !important;
209 | }
210 | .codehilite .mf {
211 | color: #ae81ff !important;
212 | }
213 | .codehilite .mh {
214 | color: #ae81ff !important;
215 | }
216 | .codehilite .mi {
217 | color: #ae81ff !important;
218 | }
219 | .codehilite .mo {
220 | color: #ae81ff !important;
221 | }
222 | .codehilite .sb {
223 | color: #e6db74 !important;
224 | }
225 | .codehilite .sc {
226 | color: #e6db74 !important;
227 | }
228 | .codehilite .sd {
229 | color: #e6db74 !important;
230 | }
231 | .codehilite .s2 {
232 | color: #e6db74 !important;
233 | }
234 | .codehilite .se {
235 | color: #ae81ff !important;
236 | }
237 | .codehilite .sh {
238 | color: #e6db74 !important;
239 | }
240 | .codehilite .si {
241 | color: #e6db74 !important;
242 | }
243 | .codehilite .sx {
244 | color: #e6db74 !important;
245 | }
246 | .codehilite .sr {
247 | color: #e6db74 !important;
248 | }
249 | .codehilite .s1 {
250 | color: #e6db74 !important;
251 | }
252 | .codehilite .ss {
253 | color: #e6db74 !important;
254 | }
255 | .codehilite .bp {
256 | color: #f8f8f2 !important;
257 | }
258 | .codehilite .vc {
259 | color: #f8f8f2 !important;
260 | }
261 | .codehilite .vg {
262 | color: #f8f8f2 !important;
263 | }
264 | .codehilite .vi {
265 | color: #f8f8f2 !important;
266 | }
267 | .codehilite .il {
268 | color: #ae81ff !important;
269 | }
270 | .codehilite .gu {
271 | color: #8a8f98 !important;
272 | }
273 | .codehilite .gd {
274 | color: #9c1042 !important;
275 | background-color: #eaa;
276 | }
277 | .codehilite .gi {
278 | color: #364c0a !important;
279 | background-color: #91e891;
280 | }
281 | .md-clipboard:before {
282 | color: rgba(255, 255, 255, 0.31);
283 | }
284 | .codehilite:hover .md-clipboard:before, .md-typeset .highlight:hover .md-clipboard:before, pre:hover .md-clipboard:before {
285 | color: rgba(255, 255, 255, 0.6);
286 | }
287 | .md-typeset summary:after {
288 | color: rgba(255, 255, 255, 0.26);
289 | }
290 | .md-typeset .admonition.example > .admonition-title, .md-typeset .admonition.example > summary, .md-typeset details.example > .admonition-title, .md-typeset details.example > summary {
291 | background-color: rgba(154, 109, 255, 0.21);
292 | }
293 | .md-nav__link[data-md-state='blur'] {
294 | color: #aec0ff;
295 | }
296 | .md-typeset .footnote {
297 | color: #888484 !important;
298 | }
299 | .md-typeset .footnote-ref:before {
300 | border-color: #888484 !important;
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/docs_es/css/styles.css:
--------------------------------------------------------------------------------
1 | .text-center {
2 | text-align: center;
3 | }
4 |
5 | article img {
6 | border: 1px solid #eee;
7 | box-shadow: 0 0 1em #ccc;
8 | margin: 30px auto 10px;
9 | }
10 |
11 | article img.emojione {
12 | border: none;
13 | box-shadow: none;
14 | margin: 0;
15 | }
16 |
17 | .md-footer-nav {
18 | background-color: rgba(0,0,0,.57);
19 | }
20 |
21 |
22 | /* Docker Branding */
23 | .md-header {
24 | background-color: #0d9cec !important;
25 | }
26 |
27 | @font-face{
28 | font-family: "Geomanist";
29 | src: url("../fonts/hinted-Geomanist-Book.ttf")
30 | }
31 |
32 | body {
33 | font-family: "Open Sans", sans-serif;
34 | font-size: 15px;
35 | font-weight: normal;
36 | font-style: normal;
37 | font-stretch: normal;
38 | line-height: 1.5;
39 | letter-spacing: normal;
40 | color: #577482;
41 | }
42 |
43 | h1, h2, h3, h4, .md-footer-nav__inner, .md-header-nav__title, footer.md-footer {
44 | font-family: Geomanist;
45 | }
46 |
47 | .md-header-nav__title {
48 | line-height: 2.9rem;
49 | }
50 |
51 | .md-header-nav__button img {
52 | width: 145px;
53 | }
--------------------------------------------------------------------------------
/docs_es/fonts/hinted-Geomanist-Book.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/fonts/hinted-Geomanist-Book.ttf
--------------------------------------------------------------------------------
/docs_es/images/docker-labs-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs_es/images/pwd-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/images/pwd-badge.png
--------------------------------------------------------------------------------
/docs_es/index.md:
--------------------------------------------------------------------------------
1 | redirect: /tutorial/
2 |
3 |
--------------------------------------------------------------------------------
/docs_es/js/custom.js:
--------------------------------------------------------------------------------
1 | $(window).load(function() {
2 | $('body').raptorize({
3 | 'enterOn' : 'konami-code'
4 | });
5 | });
--------------------------------------------------------------------------------
/docs_es/js/jquery.raptorize.1.0.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Raptorize Plugin 1.0
3 | * www.ZURB.com/playground
4 | * Copyright 2010, ZURB
5 | * Free to use under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | */
8 |
9 |
10 | (function($) {
11 |
12 | $.fn.raptorize = function(options) {
13 |
14 | //Yo' defaults
15 | var defaults = {
16 | enterOn: 'click', //timer, konami-code, click
17 | delayTime: 5000 //time before raptor attacks on timer mode
18 | };
19 |
20 | //Extend those options
21 | var options = $.extend(defaults, options);
22 |
23 | return this.each(function() {
24 |
25 | var _this = $(this);
26 | var audioSupported = false;
27 | //Stupid Browser Checking which should be in jQuery Support
28 | if ($.browser.mozilla && $.browser.version.substr(0, 5) >= "1.9.2" || $.browser.webkit) {
29 | audioSupported = true;
30 | }
31 |
32 | //Raptor Vars
33 | var raptorImageMarkup = ''
34 | var raptorAudioMarkup = '';
35 | var locked = false;
36 |
37 | //Append Raptor and Style
38 | $('body').append(raptorImageMarkup);
39 | if(audioSupported) { $('body').append(raptorAudioMarkup); }
40 | var raptor = $('#elRaptor').css({
41 | "position":"fixed",
42 | "bottom": "-700px",
43 | "right" : "0",
44 | "display" : "block"
45 | })
46 |
47 | // Animating Code
48 | function init() {
49 | locked = true;
50 |
51 | //Sound Hilarity
52 | if(audioSupported) {
53 | function playSound() {
54 | document.getElementById('elRaptorShriek').play();
55 | }
56 | playSound();
57 | }
58 |
59 | // Movement Hilarity
60 | raptor.animate({
61 | "bottom" : "0"
62 | }, function() {
63 | $(this).animate({
64 | "bottom" : "-130px"
65 | }, 100, function() {
66 | var offset = (($(this).position().left)+400);
67 | $(this).delay(300).animate({
68 | "right" : offset
69 | }, 2200, function() {
70 | raptor = $('#elRaptor').css({
71 | "bottom": "-700px",
72 | "right" : "0"
73 | })
74 | locked = false;
75 | })
76 | });
77 | });
78 | }
79 |
80 |
81 | //Determine Entrance
82 | if(options.enterOn == 'timer') {
83 | setTimeout(init, options.delayTime);
84 | } else if(options.enterOn == 'click') {
85 | _this.bind('click', function(e) {
86 | e.preventDefault();
87 | if(!locked) {
88 | init();
89 | }
90 | })
91 | } else if(options.enterOn == 'konami-code'){
92 | var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
93 | $(window).bind("keydown.raptorz", function(e){
94 | kkeys.push( e.keyCode );
95 | if ( kkeys.toString().indexOf( konami ) >= 0 ) {
96 | init();
97 | kkeys = [];
98 | // $(window).unbind('keydown.raptorz');
99 | }
100 | }, true);
101 |
102 | }
103 |
104 | });//each call
105 | }//orbit plugin call
106 | })(jQuery);
107 |
108 |
--------------------------------------------------------------------------------
/docs_es/js/raptor-sound.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/js/raptor-sound.mp3
--------------------------------------------------------------------------------
/docs_es/js/raptor-sound.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/js/raptor-sound.ogg
--------------------------------------------------------------------------------
/docs_es/js/raptor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/js/raptor.png
--------------------------------------------------------------------------------
/docs_es/tutorial/actualizando-nuestra-aplicacion/index.md:
--------------------------------------------------------------------------------
1 |
2 | Como una pequeña petición de funcionalidad, el equipo de producto nos ha pedido que cambiemos el "texto vacío" cuando no tenemos ningún elemento de la lista de tareas pendientes. Les gustaría hacer la transición a lo siguiente:
3 |
4 | > ¡Todavía no tienes tareas que realizar! ¡Agregue una tarea arriba!
5 |
6 | Bastante simple, ¿verdad? Hagamos el cambio.
7 |
8 | ## Actualizando nuestro Código Fuente
9 |
10 | 1. En el archivo `~/app/src/static/js/app.js`, actualice la línea 56 para usar el nuevo texto vacío. ([Edición de archivos en PWD, algunos consejos aquí](/pwd-tips#editing-files))
11 |
12 | ```diff
13 | -
No items yet! Add one above!
14 | +
¡Todavía no tienes tareas que realizar! ¡Agregue una tarea arriba!
15 | ```
16 |
17 | 1. Vamos a construir nuestra versión actualizada de la imagen, usando el mismo comando que usamos antes.
18 |
19 | ```bash
20 | docker build -t docker-101 .
21 | ```
22 |
23 | 1. Iniciemos un nuevo contenedor usando el código actualizado.
24 |
25 | ```bash
26 | docker run -dp 3000:3000 docker-101
27 | ```
28 |
29 | **Ops!** Probablemente has visto un error como este (los identificaciones serán diferentes):
30 |
31 | ```bash
32 | docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell
33 | (bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind for 0.0.0.0:3000 failed: port is already allocated.
34 | ```
35 |
36 | Entonces, ¿qué pasó? No podemos iniciar el nuevo contenedor porque el viejo aún está en funcionamiento. La razón por la que esto es un problema es porque ese contenedor está usando el puerto 3000 del host y sólo un proceso (contenedores incluidos) puede escuchar a un puerto específico. Para arreglar esto, necesitamos eliminar el contenedor obsoleto.
37 |
38 |
39 | ## Reemplazando nuestro contenedor obsoleto
40 |
41 | Para eliminar un contenedor, primero hay que detenerlo. Luego, puede ser eliminado.
42 |
43 | 1. Obtenga el ID del contenedor usando el comando `docker ps`.
44 |
45 | ```bash
46 | docker ps
47 | ```
48 |
49 | 1. Utilice el comando `docker stop` para detener el contenedor.
50 |
51 | ```bash
52 | # Intercambiar con el ID del docker ps
53 | docker stop
54 | ```
55 |
56 | 1. Una vez que el contenedor se ha detenido, puede eliminarlo utilizando el comando `docker rm`.
57 |
58 | ```bash
59 | docker rm
60 | ```
61 |
62 | 1. Ahora, inicia tu aplicación actualizada.
63 |
64 | ```bash
65 | docker run -dp 3000:3000 docker-101
66 | ```
67 |
68 | 1. Abre la aplicación y verás tu texto de ayuda actualizado!
69 |
70 | {: style="width:55%" }
71 | {: .text-center }
72 |
73 | !!! info "Consejo"
74 | Puede detener y eliminar un contenedor con un solo comando añadiendo la bandera "force" al comando `docker rm`. Por ejemplo: `docker rm -f `.
75 |
76 |
77 | ## Recapitulación
78 |
79 | Aunque hemos podido crear una actualización, hay dos cosas que puede que hayas notado:
80 |
81 | - Todos los artículos existentes en nuestra lista de cosas por hacer han desaparecido! Esa no es una muy buena aplicación! Hablaremos de eso pronto.
82 | - Había _muchos_ pasos involucrados para un cambio tan pequeño. En una próxima sección, hablaremos sobre cómo ver las actualizaciones de código sin necesidad de reconstruir y comenzar un nuevo contenedor cada vez que hagamos un cambio.
83 |
84 | Antes de hablar de persistencia, veremos rápidamente cómo compartir estas imágenes con otros.
85 |
--------------------------------------------------------------------------------
/docs_es/tutorial/actualizando-nuestra-aplicacion/todo-list-updated-empty-text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/actualizando-nuestra-aplicacion/todo-list-updated-empty-text.png
--------------------------------------------------------------------------------
/docs_es/tutorial/aplicaciones-multi-contenedor/multi-app-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/aplicaciones-multi-contenedor/multi-app-architecture.png
--------------------------------------------------------------------------------
/docs_es/tutorial/compartiendo-nuestra-aplicacion/index.md:
--------------------------------------------------------------------------------
1 |
2 | Ahora que hemos construido una imagen, ¡compartámosla! Para compartir imágenes Docker, debe utilizar un registro Docker. El registro por defecto es Docker Hub y es de donde vienen todas las imágenes que hemos usado.
3 |
4 | ## Crear un Repo
5 |
6 | Para subir (push) una imagen, primero tenemos que crear un repositorio en Docker Hub.
7 |
8 | 1. Ir a [Docker Hub](https://hub.docker.com) e identifíquese si es necesario.
9 |
10 | 1. Haga clic en el botón **Crear Repositorio**.
11 |
12 | 1. Para el nombre del repositorio, use `101-todo-app`. Asegúrese de que la visibilidad sea "pública".
13 |
14 | 1. ¡Haga clic en el botón **Crear**!
15 |
16 | Si miras en el lado derecho de la página, verás una sección llamada **Docker commands**. Esto da un comando de ejemplo que necesitará ejecutar para subir (push) su imagen a este repositorio.
17 |
18 | {: style=width:75% }
19 | {: .text-center }
20 |
21 |
22 | ## Subiendo nuestra imagen
23 |
24 | 1. De vuelta en su instancia de PWD, intente ejecutar el comando. Debería aparecer un error que se parezca a esto:
25 |
26 | ```plaintext
27 | $ docker push dockersamples/101-todo-app
28 | The push refers to repository [docker.io/dockersamples/101-todo-app]
29 | An image does not exist locally with the tag: dockersamples/101-todo-app
30 | ```
31 |
32 | ¿Por qué falló? El comando push estaba buscando una imagen llamada dockersamples/101-todo-app, pero no la encontró. Si ejecuta `docker image ls`, tampoco verá uno.
33 |
34 | Para arreglar esto, necesitamos "etiquetar" nuestra imagen, lo que básicamente significa darle otro nombre.
35 |
36 | 1. Inicie su sesión en Docker Hub con el comando `docker login -u TU-NOMBRE-DE-USUARIO`.
37 |
38 | 1. Utilice el comando `docker tag` para dar un nuevo nombre a la imagen `docker-101`. Asegúrate de cambiar "TU-NOMBRE-DE-USUARIO" por tu ID de Docker.
39 |
40 | ```bash
41 | docker tag docker-101 TU-NOMBRE-DE-USUARIO/101-todo-app
42 | ```
43 |
44 | 1. Ahora intente su comando para subir la imagen de nuevo. Si está copiando el valor de Docker Hub, puede omitir la parte de `tagname`, ya que no añadimos una etiqueta al nombre de la imagen.
45 |
46 | ```bash
47 | docker push TU-NOMBRE-DE-USUARIO/101-todo-app
48 | ```
49 |
50 | ## Ejecutar nuestra imagen en una nueva instancia
51 |
52 | Ahora que nuestra imagen ha sido construida e introducida en un registro, ¡vamos a intentar ejecutar nuestra aplicación en una instancia que nunca ha visto este contenedor!
53 |
54 | 1. De vuelta en PWD, haga clic en **Añadir Nueva Instancia** para crear una nueva instancia.
55 |
56 | 1. En la nueva instancia, inicia tu nueva aplicación.
57 |
58 | ```bash
59 | docker run -dp 3000:3000 TU-NOMBRE-DE-USUARIO/101-todo-app
60 | ```
61 |
62 | Deberías ver que la imagen es descargada y ¡eventualmente puesta en marcha!
63 |
64 | 1. Haz clic en la insignia 3000 cuando aparezca y deberías ver la aplicación con tus modificaciones ¡Hurra!
65 |
66 |
67 | ## Recapitulación
68 |
69 | En esta sección, aprendimos a compartir nuestras imágenes subiéndolas a un registro. Luego fuimos a una nueva instancia y pudimos ejecutar la nueva imagen. Esto es bastante común en los Pipelines de CI, donde el Pipeline creará la imagen y la subirá a un registro y entonces el entorno de producción podrá utilizar la última versión de la imagen.
70 |
71 | Ahora que tenemos eso resuelto, volvamos a lo que notamos al final de la última sección. Como recordatorio, notamos que cuando reiniciamos la aplicación, perdimos todos los elementos de nuestra lista de tareas pendientes. Obviamente, esa no es una gran experiencia de usuario, ¡así que aprendamos cómo podemos conservar los datos en los reinicios!
--------------------------------------------------------------------------------
/docs_es/tutorial/compartiendo-nuestra-aplicacion/push-command.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/compartiendo-nuestra-aplicacion/push-command.png
--------------------------------------------------------------------------------
/docs_es/tutorial/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | next_page: app.md
3 | ---
4 |
5 | ## El comando que acaba de ejecutar
6 |
7 | Felicitaciones! Ha iniciado el contenedor para este tutorial!
8 | Primero vamos a explicar el comando que acabas de ejecutar. Por si lo olvidaste, aquí está el comando:
9 |
10 | ```cli
11 | docker run -d -p 80:80 dockersamples/101-tutorial
12 | ```
13 |
14 | Notarás que se están usando algunas banderas. Aquí hay más información sobre ellos:
15 |
16 | - `-d` - ejecuta el contenedor en modo independiente (tarea de fondo o segundo plano).
17 | - `-p 80:80` - asigna el puerto 80 del host al puerto 80 del contenedor
18 | - `dockersamples/101-tutorial` - la imagen a utilizar
19 |
20 | !!! info "Consejo"
21 | Puede combinar banderas de un solo carácter para acortar el comando completo.
22 | Por ejemplo, el comando anterior podría escribirse como:
23 | ```
24 | docker run -dp 80:80 dockersamples/101-tutorial
25 | ```
26 |
27 | ## ¿Qué es un contenedor?
28 |
29 | Ahora que ha ejecutado un contenedor, ¿qué es un contenedor? En pocas palabras, un contenedor es simplemente otro proceso en su máquina que ha sido aislado de todos los demás procesos en la máquina anfitriona (máquina host). Ese aislamiento aprovecha [namespaces del kernel y cgroups](https://medium.com/@saschagrunert/demystifying-containers-part-i-kernel-space-2c53d6979504), características que han estado en Linux durante mucho tiempo. Docker ha trabajado para que estas capacidades sean accesibles y fáciles de usar.
30 |
31 | !!! info "Creación de contenedores a partir de Scratch"
32 | Si quieres ver cómo se construyen los contenedores desde cero, Liz Rice de Aqua Security tiene una fantástica charla en la que crea un contenedor desde cero en Go. Aunque ella hace un simple contenedor, esta charla no entra en pronfundidad sobre el manejo de red, construcción de imágenes para el sistema de archivos, y más. Pero, da una _fantástica_ inmersión profunda en cómo están funcionando las cosas.
33 |
34 |
35 |
36 | ## ¿Qué es una imagen de contenedor?
37 |
38 | Cuando se ejecuta un contenedor, utiliza un sistema de archivos aislado. Este sistema de archivos personalizado es proporcionado por una **imagen del contenedor**. Dado que la imagen contiene el sistema de archivos del contenedor, debe contener todo lo necesario para ejecutar una aplicación: todas las dependencias, configuración, scripts, binarios, etc. La imagen también contiene otra configuración para el contenedor, como variables de entorno, un comando predeterminado para ejecutar y otros metadatos.
39 |
40 | Más adelante nos adentraremos más en las imágenes, cubriendo temas como las capas, las mejores prácticas y mucho más.
41 |
42 | !!! info
43 | Si está familiarizado con `chroot`, piense en un contenedor como una versión extendida de `chroot`. El sistema de archivos simplemente viene de la imagen. Pero, un contenedor añade un aislamiento adicional que no está disponible cuando se usa simplemente chroot.
44 |
45 |
--------------------------------------------------------------------------------
/docs_es/tutorial/nuestra-aplicacion/index.md:
--------------------------------------------------------------------------------
1 | Para el resto de este tutorial, trabajaremos con un simple gestor de listas de tareas (todo list) que se está ejecutando en Node. Si no estás familiarizado con Node, ¡no te preocupes! ¡No se necesita experiencia real con JavaScript!
2 |
3 | En este punto, su equipo de desarrollo es bastante pequeño y usted simplemente está construyendo una aplicación para probar su MVP (producto mínimo viable). Quieres mostrar cómo funciona y lo que es capaz de hacer sin necesidad de pensar en cómo funcionará para un equipo grande, múltiples desarrolladores, etc.
4 |
5 | {: style="width:50%;" }
6 | { .text-center }
7 |
8 | ## Introduciendo nuestra aplicación en PWD
9 |
10 | Antes de que podamos ejecutar la aplicación, necesitamos obtener el código fuente de la aplicación en el entorno Play with Docker. Para proyectos reales, puedes clonar el repositorio. Pero, en este caso, usted subirá un archivo ZIP.
11 |
12 | 1. [Descarga el zip](/assets/app.zip) y cárgalo a Play with Docker. Como consejo, puede arrastrar y soltar el zip (o cualquier otro archivo) sobre el terminal en PWD.
13 |
14 | 1. En el terminal PWD, extraiga el archivo zip.
15 |
16 | ```bash
17 | unzip app.zip
18 | ```
19 |
20 | 1. Cambie su directorio de trabajo actual a la nueva carpeta 'app'.
21 |
22 | ```bash
23 | cd app/
24 | ```
25 |
26 | 1. En este directorio, debería ver una aplicación simple basada en Node.
27 |
28 | ```bash
29 | ls
30 | package.json spec src yarn.lock
31 | ```
32 |
33 | ## Creación de la imagen del contenedor con la aplicación
34 |
35 | Para construir la aplicación, necesitamos usar un `Dockerfile`. Un Dockerfile es simplemente un script de instrucciones basado en texto que se utiliza para crear una imagen de contenedor. Si ya ha creado Dockerfiles anteriormente, es posible que aparezcan algunos defectos en el Dockerfile que se muestra a continuación. Pero, ¡no te preocupes! Los revisaremos.
36 |
37 | 1. Cree un archivo llamado Dockerfile con el siguiente contenido.
38 |
39 | ```dockerfile
40 | FROM node:10-alpine
41 | WORKDIR /app
42 | COPY . .
43 | RUN yarn install --production
44 | CMD ["node", "/app/src/index.js"]
45 | ```
46 |
47 | 1. Construya la imagen del contenedor usando el comando `docker build`.
48 |
49 | ```bash
50 | docker build -t docker-101 .
51 | ```
52 |
53 | Este comando usó el Dockerfile para construir una nueva imagen del contenedor. Puede que haya notado que se han descargado muchas "capas". Esto se debe a que instruimos al constructor que queríamos empezar desde la imagen `node:10-alpine`. Pero, como no teníamos eso en nuestra máquina, esa imagen necesitaba ser descargada.
54 |
55 | Después de eso, copiamos en nuestra aplicación y usamos `yarn` para instalar las dependencias de nuestra aplicación. La directiva `CMD` especifica el comando por defecto que se ejecutará al iniciar un contenedor desde esta imagen.
56 |
57 | ## Iniciando el contenedor de la aplicación
58 |
59 | Ahora que tenemos una imagen, vamos a ejecutar la aplicación! Para ello, usaremos el comando `docker run` (¿recuerdas lo de antes?).
60 |
61 | 1. Inicie su contenedor usando el comando `docker run`:
62 |
63 | ```bash
64 | docker run -dp 3000:3000 docker-101
65 | ```
66 |
67 | ¿Recuerdas las banderas `-d` y `-p`? Estamos ejecutando el nuevo contenedor en modo "separado" (en segundo plano) y creando un mapeo entre el puerto 3000 del host y el puerto 3000 del contenedor.
68 |
69 | 1. Abra la aplicación haciendo clic en la insignia "3000" en la parte superior de la interfaz PWD. Una vez abierto, ¡debería tener una lista de cosas por hacer vacía!
70 |
71 | {: style="width:450px;margin-top:20px;"}
72 | {: .text-center }
73 |
74 | 1. Adelante, agregue uno o dos elementos y vea que funciona como usted espera. Puede marcar las posiciones como completas y eliminarlas.
75 |
76 | En este punto, deberías tener un administrador de listas de cosas por hacer con unos cuantos elementos, ¡todos construidos por ti! Ahora, hagamos algunos cambios y aprendamos sobre el manejo de nuestros contenedores.
77 |
78 | ## Recapitulación
79 |
80 | En esta breve sección, aprendimos lo básico sobre la construcción de una imagen de contenedor y creamos un Dockerfile para hacerlo. Una vez que construimos una imagen, iniciamos el contenedor y ¡vimos la aplicación en ejecución!
81 |
82 | A continuación, vamos a hacer una modificación a nuestra aplicación y aprender a actualizar nuestra aplicación en ejecución con una nueva imagen. En el camino, aprenderemos algunos otros comandos útiles.
83 |
--------------------------------------------------------------------------------
/docs_es/tutorial/nuestra-aplicacion/todo-list-empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/nuestra-aplicacion/todo-list-empty.png
--------------------------------------------------------------------------------
/docs_es/tutorial/nuestra-aplicacion/todo-list-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/nuestra-aplicacion/todo-list-sample.png
--------------------------------------------------------------------------------
/docs_es/tutorial/persistiendo-nuestra-base-de-datos/index.md:
--------------------------------------------------------------------------------
1 |
2 | En caso de que no lo hayas notado, nuestra lista de cosas por hacer está siendo limpiada cada vez que lanzamos el contenedor. ¿Por qué sucede esto? Vamos a ver cómo funciona el contenedor.
3 |
4 | ## El sistema de archivos del contenedor
5 |
6 | Cuando un contenedor se ejecuta, utiliza las diferentes capas de una imagen para su sistema de archivos. Cada contenedor también tiene su propio "espacio" para crear/actualizar/quitar archivos. Cualquier cambio no se verá en otro contenedor, _incluso si_ están usando la misma imagen.
7 |
8 | {: style="width: 70%;" }
9 | {: .text-center }
10 |
11 |
12 | ### Veamos esto en la práctica
13 |
14 | Para ver esto en acción, vamos a iniciar dos contenedores y crear un archivo en cada uno. Lo que verá es que los archivos creados en un contenedor no están disponibles en otro.
15 |
16 | 1. Inicie un contenedor `ubuntu` que creará un archivo llamado `/data.txt` con un número aleatorio entre 1 y 10000.
17 |
18 | ```bash
19 | docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
20 | ```
21 |
22 | En caso de que se esté preguntando por el comando, estamos iniciando un shell bash e invocando dos comandos (por qué tenemos el `&&`). La primera parte escoge un único número aleatorio y lo escribe en `/data.txt`. El segundo comando es simplemente mirar un archivo para mantener el contenedor funcionando.
23 |
24 | 1. Para validar el resultado, podemos ver la salida por `exec` en el contenedor. Para ello, necesita obtener el ID del contenedor (utilice `docker ps` para obtenerlo).
25 |
26 | ```bash
27 | docker exec cat /data.txt
28 | ```
29 |
30 | Deberías ver un número al azar
31 |
32 | 1. Ahora, vamos a empezar otro contenedor `ubuntu` (la misma imagen) y veremos que no tenemos el mismo archivo.
33 |
34 | ```bash
35 | docker run -it ubuntu ls /
36 | ```
37 |
38 | ¡Y mira! No hay ningún archivo `data.txt` allí. Esto se debe a que sólo fue escrito en el espacio del primer contenedor.
39 |
40 | 1. Adelante, proceda a eliminar el primer contenedor usando el comando `docker rm -f `.
41 |
42 |
43 | ## Volúmenes de Contenedores
44 |
45 | Con el experimento anterior, vimos que cada contenedor es efectivamente de sólo lectura. Mientras que los contenedores pueden crear, actualizar y eliminar archivos, esos cambios se pierden cuando se elimina el contenedor. Con los volúmenes, podemos cambiar todo esto.
46 |
47 | [Volúmenes](https://docs.docker.com/storage/volumes/) proporcionan la capacidad de conectar rutas específicas del sistema de archivos del contenedor de nuevo a la máquina anfitriona. Si se monta un directorio en el contenedor, los cambios en ese directorio también se ven en el equipo host. Si montamos ese mismo directorio en los reinicios del contenedor, veremos los mismos archivos.
48 |
49 | Hay dos tipos principales de volúmenes. Eventualmente usaremos ambos, pero empezaremos con **volúmenes nombrados**.
50 |
51 |
52 |
53 | ## Persistiendo datos de nuestro Gestor de Tareas (todo app)
54 |
55 | Por defecto, la aplicación "todo app" almacena sus datos en un archivo de base de datos [SQLite](https://www.sqlite.org/index.html) en `/etc/todos/todo.db`. Si no estás familiarizado con SQLite, ¡no te preocupes! Es simplemente una base de datos relacional en la que todos los datos se almacenan en un único archivo. Aunque esto no es lo mejor para aplicaciones a gran escala, funciona para pequeñas demostraciones. Hablaremos de cambiar esto a un motor de base de datos real más tarde.
56 |
57 | Con la base de datos siendo un solo archivo, si podemos mantener ese archivo en el host y ponerlo a disposición del siguiente contenedor, debería ser capaz de retomarlo donde lo dejó el último. Creando un volumen y adjuntándolo (a menudo llamado "montaje") al directorio en el que se almacenan los datos, podemos persistir en los datos. Mientras nuestro contenedor escribe en el archivo `todo.db`, persistirá en el host del volumen.
58 |
59 | Como se mencionó anteriormente, vamos a usar un **volumen nombrado**. Piense en un volumen nombrado como un simple cubo de datos. Docker mantiene la ubicación física en el disco y sólo necesita recordar el nombre del volumen. Cada vez que utilice el volumen, Docker se asegurará de que se proporcionen los datos correctos.
60 |
61 | 1. Cree un volumen utilizando el comando `docker volume create`.
62 |
63 | ```bash
64 | docker volume create todo-db
65 | ```
66 |
67 | 1. Inicie el contenedor `docker-101`, pero añada el indicador `-v` para especificar un montaje de volumen. Usaremos el volumen nombrado y lo montaremos en `/etc/todos`, que capturará todos los archivos creados en la ruta.
68 |
69 | ```bash
70 | docker run -dp 3000:3000 -v todo-db:/etc/todos docker-101
71 | ```
72 |
73 | 1. Una vez que el contenedor se inicie, abra la aplicación y añada algunos elementos a su lista de tareas pendientes.
74 |
75 | {: style="width: 55%; " }
76 | {: .text-center }
77 |
78 | 1. Proceda a eliminar el contenedor `docker-101`. Utilice `docker ps` para obtener el ID y luego `docker rm -f ` para eliminarlo.
79 |
80 | 1. Inicie un nuevo contenedor usando el mismo comando del paso 2.
81 |
82 | 1. Abra la aplicación. Usted debe ver sus tareas todavía en su lista
83 |
84 | 1. Adelante, proceda a eliminar el contenedor cuando haya terminado de revisar su lista.
85 |
86 | ¡Genial! ¡Ahora ha aprendido a persistir los datos de su aplicación!
87 |
88 | !!! info "Consejo"
89 | Aunque los volúmenes nombrados y los montajes de enlace (de los que hablaremos en un minuto) son los dos tipos principales de volúmenes soportados por una instalación de motor Docker predeterminada, hay muchos plugins de controladores de volumen disponibles para soportar NFS, SFTP, NetApp y mucho más. Esto será especialmente importante una vez que comience a ejecutar contenedores en múltiples hosts en un entorno agrupado con Swarm, Kubernetes, etc.
90 |
91 |
92 | ## Sumérjase en nuestro Volumen
93 |
94 | Mucha gente se pregunta con frecuencia "¿Dónde está Docker _actualmente_ almacenando mis datos cuando uso un volumen nombrado?" Si quiere saber, puede usar el comando `docker volume inspect`.
95 |
96 | ```bash
97 | docker volume inspect todo-db
98 | [
99 | {
100 | "CreatedAt": "2019-09-28T21:37:36Z",
101 | "Driver": "local",
102 | "Labels": {},
103 | "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
104 | "Name": "todo-db",
105 | "Options": {},
106 | "Scope": "local"
107 | }
108 | ]
109 | ```
110 |
111 | El `Mountpoint` es la ubicación real en el disco donde se almacenan los datos. Tenga en cuenta que en la mayoría de los equipos, necesitará tener acceso de root para acceder a este directorio desde el host. Pero, ahí es donde está.
112 |
113 |
114 | ## Recapitulación
115 |
116 | En este punto, tenemos una aplicación en funcionamiento que puede sobrevivir a los reinicios. ¡Podemos mostrarlo a nuestros inversores y esperar que puedan captar nuestra visión!
117 |
118 | Sin embargo, vimos anteriormente que la reconstrucción de imágenes para cada cambio toma bastante tiempo. Tiene que haber una forma mejor de hacer cambios, ¿verdad? Con el uso de `bind mounts` (que ya hemos mencionado anteriormente), ¡hay una forma mejor de hacerlo! Echemos un vistazo a eso ahora!
119 |
--------------------------------------------------------------------------------
/docs_es/tutorial/persistiendo-nuestra-base-de-datos/items-added.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/persistiendo-nuestra-base-de-datos/items-added.png
--------------------------------------------------------------------------------
/docs_es/tutorial/persistiendo-nuestra-base-de-datos/sistemas-de-archivos-de-un-contenedor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/persistiendo-nuestra-base-de-datos/sistemas-de-archivos-de-un-contenedor.png
--------------------------------------------------------------------------------
/docs_es/tutorial/que-sigue/index.md:
--------------------------------------------------------------------------------
1 |
2 | Aunque hemos terminado con nuestro taller, todavía hay mucho más que aprender acerca de los contenedores! No vamos a hacer una inmersión profunda aquí, pero aquí hay algunas otras áreas para ver a continuación!
3 |
4 | ## Orquestación de contenedores
5 |
6 | El funcionamiento de los contenedores en la producción es difícil. Usted no quiere iniciar sesión en una máquina y simplemente ejecutar un `docker run` o `docker-composition up`. ¿Por qué no? Bueno, ¿qué pasa si los contenedores mueren? ¿Cómo se puede escalar a través de varias máquinas? La orquestación de contenedores resuelve este problema. Herramientas como Kubernetes, Swarm, Nomad y ECS ayudan a resolver este problema, todas estas herramientas lo hacen un poco diferente.
7 |
8 | La idea general es que usted tiene "gestores" que reciben **estado esperado**. Este estado podría ser "Quiero ejecutar dos instancias de mi aplicación web y exponer el puerto 80." Los gestores entonces miran todas las máquinas en el cluster y delegan el trabajo a los nodos "trabajadores". Los gestores están atentos a los cambios (como la salida de un contenedor) y luego trabajan para hacer que el **estado real** refleje el estado esperado.
9 |
10 |
11 | ## Proyectos de la Cloud Native Computing Foundation
12 |
13 | La CNCF es un proveedor neutral para varios proyectos de código abierto, incluyendo Kubernetes, Prometheus, Envoy, Linkerd, NATS, y más! Puede ver los [proyectos graduados e incubados aquí](https://www.cncf.io/projects/) y todo [lo relacionado a CNCF](https://landscape.cncf.io/). Hay un montón de proyectos para ayudar a resolver problemas de monitoreo, registro, seguridad, registros de imágenes, mensajería y más!
14 |
15 | Por lo tanto, si es nuevo en el mundo de los contenedores y en el desarrollo de aplicaciones nativas de la nube, ¡bienvenido! Por favor, conéctese con la comunidad, haga preguntas y siga aprendiendo! Estamos emocionados de tenerte!
16 |
--------------------------------------------------------------------------------
/docs_es/tutorial/usando-bind-mounts/index.md:
--------------------------------------------------------------------------------
1 |
2 | En el capítulo anterior, hablamos y usamos un **volúmenes nombrados** para mantener los datos en nuestra base de datos. Los volúmenes nombrados son excelentes si simplemente queremos almacenar datos, ya que no tenemos que preocuparnos por _donde_ se almacenan los datos.
3 |
4 | Con **bind mounts**, controlamos el punto de montaje exacto en el host. Podemos utilizar esto para persistir en los datos, pero a menudo se utiliza para proporcionar datos adicionales en contenedores. Cuando trabajamos en una aplicación, podemos usar bind mount para montar nuestro código fuente en el contenedor para que vea los cambios de código, responda y nos permita ver los cambios de inmediato.
5 |
6 | Para aplicaciones basadas en Node, [nodemon](https://npmjs.com/package/nodemon) es una gran herramienta para observar los cambios en los archivos y luego reiniciar la aplicación. Existen herramientas equivalentes en la mayoría de los demás lenguajes y frameworks.
7 |
8 | ## Comparaciones rápidas de tipos de volumen
9 |
10 | Bind mounts y volúmenes nombrados son los dos tipos principales de volúmenes que vienen con el motor Docker. Sin embargo, hay controladores de volumen adicionales disponibles para soportar otros casos de uso. ([SFTP](https://github.com/vieux/docker-volume-sshfs), [Ceph](https://ceph.com/geen-categorie/getting-started-with-the-docker-rbd-volume-plugin/), [NetApp](https://netappdvp.readthedocs.io/en/stable/), [S3](https://github.com/elementar/docker-s3-volume), y más).
11 |
12 | | | Volúmenes Nombrados | Bind Mounts |
13 | | - | ------------- | ----------- |
14 | | Ubicación del Anfitrión (Host) | Docker escoge | Usted controla |
15 | | Ejemplo de Mount (usando `-v`) | volumen:/usr/local/data | /path/to/data:/usr/local/data |
16 | | Llena el nuevo volumen con el contenido del contenedor | Si | No |
17 | | Soporta controladores de volumen | Si | No |
18 |
19 |
20 | ## Inicio de un contenedor Modo-Dev
21 |
22 | Para ejecutar nuestro contenedor para soportar un flujo de trabajo de desarrollo, haremos lo siguiente:
23 |
24 | - Montar nuestro código fuente en el contenedor
25 | - Instalar todas las dependencias, incluyendo las dependencias "dev".
26 | - Iniciar nodemon para observar los cambios en el sistema de archivos
27 |
28 | Así que, ¡hagámoslo!
29 |
30 | 1. Asegúrese de no tener ningún contenedor `docker-101` en funcionamiento.
31 |
32 | 1. Ejecute el siguiente comando. Le explicaremos lo que pasa después:
33 |
34 | ```bash
35 | docker run -dp 3000:3000 \
36 | -w /app -v $PWD:/app \
37 | node:10-alpine \
38 | sh -c "yarn install && yarn run dev"
39 | ```
40 |
41 | - `-dp 3000:3000` - igual que antes. Ejecutar en modo independiente (en segundo plano) y crear una asignación de puertos
42 | - `-w /app` - establece el "directorio de trabajo" o el directorio actual desde el que se ejecutará el comando
43 | - `node:10-alpine` - la imagen a utilizar. Tenga en cuenta que esta es la imagen base de nuestra aplicación desde el Dockerfile
44 | - `sh -c "yarn install && yarn run dev"` - el comando. Estamos iniciando una shell usando `sh` (alpine no tiene `bash`) y ejecutando `yarn install` para instalar _todas las_ dependencias y luego ejecutando `yarn run dev`. Si miramos en el `package.json`, veremos que el script `dev` está empezando `nodemon`.
45 |
46 | 1. Puede ver los registros usando `docker logs -f `.
47 |
48 | ```bash
49 | docker logs -f
50 | $ nodemon src/index.js
51 | [nodemon] 1.19.2
52 | [nodemon] to restart at any time, enter `rs`
53 | [nodemon] watching dir(s): *.*
54 | [nodemon] starting `node src/index.js`
55 | Using sqlite database at /etc/todos/todo.db
56 | Listening on port 3000
57 | ```
58 |
59 | Cuando termine de ver los registros, salga pulsando `Ctrl`+`C`.
60 |
61 | 1. Ahora, hagamos un cambio en la aplicación. En el archivo `src/static/js/app.js`, cambiemos el botón "Add Item" para decir simplemente "Agregar". Este cambio será en la línea 109.
62 |
63 | ```diff
64 | - {submitting ? 'Adding...' : 'Add Item'}
65 | + {submitting ? 'Adding...' : 'Agregar'}
66 | ```
67 |
68 | 1. Simplemente actualice la página (o ábrala) y verá el cambio reflejado en el navegador casi inmediatamente. El servidor de Node puede tardar unos segundos en reiniciarse, así que si obtiene un error, intente actualizarlo después de unos segundos.
69 |
70 | {: style="width:75%;"}
71 | {: .text-center }
72 |
73 | 1. Siéntase libre de hacer cualquier otro cambio que desee hacer. Cuando haya terminado, detenga el contenedor y cree su nueva imagen usando `docker build -t docker-101 .`.
74 |
75 |
76 | El uso de bind mounts es _muy_ común en las configuraciones de desarrollo local. La ventaja es que la máquina de desarrollo no necesita tener todas las herramientas de construcción y entornos instalados. Con un solo comando `docker run`, el entorno de desarrollo se levanta y está listo para funcionar. Hablaremos de Docker Compose en un futuro, ya que esto nos ayudará a simplificar nuestros comandos (ya estamos recibiendo muchas banderas).
77 |
78 | ## Recapitulación
79 |
80 | En este punto, podemos persistir en nuestra base de datos y responder rápidamente a las necesidades y demandas de nuestros inversores y fundadores. ¡Hurra! Pero, ¿adivina qué? Recibimos grandes noticias!
81 |
82 | **¡Su proyecto ha sido seleccionado para ser llevado a producción!**
83 |
84 | Para ir a producción, necesitamos migrar nuestra base de datos, pasando de trabajar en SQLite a algo que pueda escalar un poco mejor. Para simplificar, nos mantendremos con una base de datos relacional y cambiaremos nuestra aplicación para usar MySQL. Pero, ¿cómo debemos ejecutar MySQL? ¿Cómo permitimos que los contenedores se comuniquen entre sí? ¡Hablaremos de eso después!
85 |
--------------------------------------------------------------------------------
/docs_es/tutorial/usando-bind-mounts/updated-add-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_es/tutorial/usando-bind-mounts/updated-add-button.png
--------------------------------------------------------------------------------
/docs_pt-br/css/dark-mode.css:
--------------------------------------------------------------------------------
1 | @media (prefers-color-scheme: dark) {
2 | .md-main {
3 | color: rgba(255, 255, 255, 0.75) !important;
4 | background-color: #36393e !important;
5 | }
6 |
7 | article img {
8 | box-shadow: 0 0 1em #000;
9 | }
10 |
11 | .md-main h1 {
12 | color: rgba(255, 255, 255, 0.8) !important;
13 | }
14 | blockquote {
15 | color: rgba(255, 255, 255, 0.75) !important;
16 | }
17 | table {
18 | background-color: #616161 !important;
19 | }
20 | tbody {
21 | background-color: #484848 !important;
22 | }
23 | .md-sidebar__scrollwrap::-webkit-scrollbar-thumb {
24 | background-color: #e0e0e0 !important;
25 | }
26 | .md-nav {
27 | color: rgba(255, 255, 255, 0.8) !important;
28 | background-color: #36393e !important;
29 | }
30 | html .md-nav--primary .md-nav__title:before {
31 | color: #fafafa !important;
32 | }
33 | .md-nav__title {
34 | color: rgba(255, 255, 255, 0.9) !important;
35 | background-color: #36393e !important;
36 | }
37 | .md-nav--primary .md-nav__link:after {
38 | color: #fafafa !important;
39 | }
40 | .md-nav__list {
41 | color: rgba(255, 255, 255, 0.8) !important;
42 | background-color: #36393e !important;
43 | }
44 | .md-nav__item {
45 | color: rgba(255, 255, 255, 0.7) !important;
46 | background-color: #36393e !important;
47 | }
48 | .md-search__scrollwrap::-webkit-scrollbar-thumb {
49 | background-color: #e0e0e0 !important;
50 | }
51 | .md-search__scrollwrap {
52 | background-color: #44484e !important;
53 | }
54 | .md-search-result__article--document:before {
55 | color: #eee !important;
56 | }
57 | .md-search-result__list {
58 | color: #eee !important;
59 | background-color: #36393e !important;
60 | }
61 | .md-search-result__meta {
62 | background-color: #eee !important;
63 | }
64 | .md-search-result__teaser {
65 | color: #bdbdbd !important;
66 | }
67 | .md-typeset code {
68 | color: white !important;
69 | /* box-shadow: 0.29412em 0 0 hsla(0, 0%, 100%, 0.07),
70 | -0.29412em 0 0 hsla(0, 0%, 100%, 0.1);*/
71 | }
72 | .md-typeset a code {
73 | color: #94acff !important;
74 | }
75 | .md-typeset a:hover code {
76 | text-decoration: underline;
77 | }
78 | .linenos {
79 | color: #f5f5f5 !important;
80 | background-color: #313131 !important;
81 | }
82 | .codehilite {
83 | background-color: #44484e !important;
84 | }
85 | .md-typeset .codehilite::-webkit-scrollbar {
86 | height: 1rem !important;
87 | }
88 | .codehilite pre {
89 | color: #fafafa !important;
90 | background-color: transparent !important;
91 | }
92 | .codehilite .hll {
93 | background-color: #272822 !important;
94 | }
95 | .codehilite .c {
96 | color: #8a8f98 !important;
97 | }
98 | .codehilite .err {
99 | color: #960050 !important;
100 | background-color: #1e0010 !important;
101 | }
102 | .codehilite .k {
103 | color: #66d9ef !important;
104 | }
105 | .codehilite .l {
106 | color: #ae81ff !important;
107 | }
108 | .codehilite .n {
109 | color: #f8f8f2 !important;
110 | }
111 | .codehilite .o {
112 | color: #f92672 !important;
113 | }
114 | .codehilite .p {
115 | color: #f8f8f2 !important;
116 | }
117 | .codehilite .cm {
118 | color: #8a8f98 !important;
119 | }
120 | .codehilite .cp {
121 | color: #8a8f98 !important;
122 | }
123 | .codehilite .c1 {
124 | color: #8a8f98 !important;
125 | }
126 | .codehilite .cs {
127 | color: #8a8f98 !important;
128 | }
129 | .codehilite .ge {
130 | font-style: italic !important;
131 | }
132 | .codehilite .gs {
133 | font-weight: bold !important;
134 | }
135 | .codehilite .kc {
136 | color: #66d9ef !important;
137 | }
138 | .codehilite .kd {
139 | color: #66d9ef !important;
140 | }
141 | .codehilite .kn {
142 | color: #f92672 !important;
143 | }
144 | .codehilite .kp {
145 | color: #66d9ef !important;
146 | }
147 | .codehilite .kr {
148 | color: #66d9ef !important;
149 | }
150 | .codehilite .kt {
151 | color: #66d9ef !important;
152 | }
153 | .codehilite .ld {
154 | color: #e6db74 !important;
155 | }
156 | .codehilite .m {
157 | color: #ae81ff !important;
158 | }
159 | .codehilite .s {
160 | color: #e6db74 !important;
161 | }
162 | .codehilite .na {
163 | color: #a6e22e !important;
164 | }
165 | .codehilite .nb {
166 | color: #f8f8f2 !important;
167 | }
168 | .codehilite .nc {
169 | color: #a6e22e !important;
170 | }
171 | .codehilite .no {
172 | color: #66d9ef !important;
173 | }
174 | .codehilite .nd {
175 | color: #a6e22e !important;
176 | }
177 | .codehilite .ni {
178 | color: #f8f8f2 !important;
179 | }
180 | .codehilite .ne {
181 | color: #a6e22e !important;
182 | }
183 | .codehilite .nf {
184 | color: #a6e22e !important;
185 | }
186 | .codehilite .nl {
187 | color: #f8f8f2 !important;
188 | }
189 | .codehilite .nn {
190 | color: #f8f8f2 !important;
191 | }
192 | .codehilite .nx {
193 | color: #a6e22e !important;
194 | }
195 | .codehilite .py {
196 | color: #f8f8f2 !important;
197 | }
198 | .codehilite .nt {
199 | color: #f92672 !important;
200 | }
201 | .codehilite .nv {
202 | color: #f8f8f2 !important;
203 | }
204 | .codehilite .ow {
205 | color: #f92672 !important;
206 | }
207 | .codehilite .w {
208 | color: #f8f8f2 !important;
209 | }
210 | .codehilite .mf {
211 | color: #ae81ff !important;
212 | }
213 | .codehilite .mh {
214 | color: #ae81ff !important;
215 | }
216 | .codehilite .mi {
217 | color: #ae81ff !important;
218 | }
219 | .codehilite .mo {
220 | color: #ae81ff !important;
221 | }
222 | .codehilite .sb {
223 | color: #e6db74 !important;
224 | }
225 | .codehilite .sc {
226 | color: #e6db74 !important;
227 | }
228 | .codehilite .sd {
229 | color: #e6db74 !important;
230 | }
231 | .codehilite .s2 {
232 | color: #e6db74 !important;
233 | }
234 | .codehilite .se {
235 | color: #ae81ff !important;
236 | }
237 | .codehilite .sh {
238 | color: #e6db74 !important;
239 | }
240 | .codehilite .si {
241 | color: #e6db74 !important;
242 | }
243 | .codehilite .sx {
244 | color: #e6db74 !important;
245 | }
246 | .codehilite .sr {
247 | color: #e6db74 !important;
248 | }
249 | .codehilite .s1 {
250 | color: #e6db74 !important;
251 | }
252 | .codehilite .ss {
253 | color: #e6db74 !important;
254 | }
255 | .codehilite .bp {
256 | color: #f8f8f2 !important;
257 | }
258 | .codehilite .vc {
259 | color: #f8f8f2 !important;
260 | }
261 | .codehilite .vg {
262 | color: #f8f8f2 !important;
263 | }
264 | .codehilite .vi {
265 | color: #f8f8f2 !important;
266 | }
267 | .codehilite .il {
268 | color: #ae81ff !important;
269 | }
270 | .codehilite .gu {
271 | color: #8a8f98 !important;
272 | }
273 | .codehilite .gd {
274 | color: #9c1042 !important;
275 | background-color: #eaa;
276 | }
277 | .codehilite .gi {
278 | color: #364c0a !important;
279 | background-color: #91e891;
280 | }
281 | .md-clipboard:before {
282 | color: rgba(255, 255, 255, 0.31);
283 | }
284 | .codehilite:hover .md-clipboard:before, .md-typeset .highlight:hover .md-clipboard:before, pre:hover .md-clipboard:before {
285 | color: rgba(255, 255, 255, 0.6);
286 | }
287 | .md-typeset summary:after {
288 | color: rgba(255, 255, 255, 0.26);
289 | }
290 | .md-typeset .admonition.example > .admonition-title, .md-typeset .admonition.example > summary, .md-typeset details.example > .admonition-title, .md-typeset details.example > summary {
291 | background-color: rgba(154, 109, 255, 0.21);
292 | }
293 | .md-nav__link[data-md-state='blur'] {
294 | color: #aec0ff;
295 | }
296 | .md-typeset .footnote {
297 | color: #888484 !important;
298 | }
299 | .md-typeset .footnote-ref:before {
300 | border-color: #888484 !important;
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/docs_pt-br/css/styles.css:
--------------------------------------------------------------------------------
1 | .text-center {
2 | text-align: center;
3 | }
4 |
5 | article img {
6 | border: 1px solid #eee;
7 | box-shadow: 0 0 1em #ccc;
8 | margin: 30px auto 10px;
9 | }
10 |
11 | article img.emojione {
12 | border: none;
13 | box-shadow: none;
14 | margin: 0;
15 | }
16 |
17 | .md-footer-nav {
18 | background-color: rgba(0,0,0,.57);
19 | }
20 |
21 |
22 | /* Docker Branding */
23 | .md-header {
24 | background-color: #0d9cec !important;
25 | }
26 |
27 | @font-face{
28 | font-family: "Geomanist";
29 | src: url("../fonts/hinted-Geomanist-Book.ttf")
30 | }
31 |
32 | body {
33 | font-family: "Open Sans", sans-serif;
34 | font-size: 15px;
35 | font-weight: normal;
36 | font-style: normal;
37 | font-stretch: normal;
38 | line-height: 1.5;
39 | letter-spacing: normal;
40 | color: #577482;
41 | }
42 |
43 | h1, h2, h3, h4, .md-footer-nav__inner, .md-header-nav__title, footer.md-footer {
44 | font-family: Geomanist;
45 | }
46 |
47 | .md-header-nav__title {
48 | line-height: 2.9rem;
49 | }
50 |
51 | .md-header-nav__button img {
52 | width: 145px;
53 | }
--------------------------------------------------------------------------------
/docs_pt-br/dicas-pwd/editor-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/dicas-pwd/editor-button.png
--------------------------------------------------------------------------------
/docs_pt-br/dicas-pwd/editor-display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/dicas-pwd/editor-display.png
--------------------------------------------------------------------------------
/docs_pt-br/dicas-pwd/index.md:
--------------------------------------------------------------------------------
1 |
2 | ## Criando Arquivos
3 |
4 | Se você é novo no terminal Linux, não se preocupe! O jeito mais fácil de criar um arquivo é utilizando o
5 | comando `touch`.
6 |
7 | ```bash
8 | touch Dockerfile
9 | ```
10 |
11 | Se você rodar `ls`, você verá que o arquivo foi criado. Uma vez criado, você pode utilizar as dicas **Editando Arquivos** abaixo.
12 |
13 | ## Editando Arquivos
14 |
15 | No PWD, você pode utilizar qualquer editor de texto baseado em CLI. Entretanto, sabemos que muitos não se sentem
16 | confortáveis utilizando o CLI.
17 | Você pode clicar no botão "Editor" para abrir a janela do gerenciador de arquivos.
18 |
19 | {: style=width:50% }
20 | {:.text-center}
21 |
22 | Depois de clicar no botão editor, o editor de arquivo irá abrir. Selecionando um arquivo fornecerá um editor
23 | baseado na web.
24 |
25 | {: style=width:75% }
26 | {: .text-center }
27 |
28 | ## Abrindo uma Aplicação quando não tiver o botão
29 |
30 | Se você iniciou um contêiner, mas o botão da porta não apareceu, ainda existe um jeito de abrir a aplicação.
31 |
32 | 1. Primeiro, valide se o contêiner está realmente rodando e apenas não falhou ao iniciar. Rode `docker ps` e
33 | verifique se a porta está mapeada na seção `PORTS`.
34 |
35 | ```bash
36 | $ docker ps
37 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38 | 976e7066d705 docker-101 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:3000->3000/tcp xenodochial_ritchie
39 | ```
40 |
41 | Se o contêiner falhou ao iniciar, verifique os logs do contêiner e tente descobrir o que aconteceu.
42 |
43 | 1. No PWD, procure o painel `SSH`. Ele deve mostrar algo parecido com `ssh ip172...`. Copie tudo DEPOIS da parte
44 | do `ssh` (`ip172....`).
45 |
46 | 1. Cole isso no navegador, mas NÃO aperte enter ainda. Procure o símbolo `@`. Substitua por `-PORT`. Por exemplo,
47 | se eu tivesse `ip172-18-0-22-bmf9t2ds883g009iqq80@direct.labs.play-with-docker.com` e quisesse ver a porta 3000, eu iria
48 | abrir ip172-18-0-22-bmf9t2ds883g009iqq80-3000.direct.labs.play-with-docker.com.
--------------------------------------------------------------------------------
/docs_pt-br/fonts/hinted-Geomanist-Book.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/fonts/hinted-Geomanist-Book.ttf
--------------------------------------------------------------------------------
/docs_pt-br/images/docker-labs-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs_pt-br/images/pwd-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/images/pwd-badge.png
--------------------------------------------------------------------------------
/docs_pt-br/index.md:
--------------------------------------------------------------------------------
1 | redirect: /tutorial/
2 |
3 |
--------------------------------------------------------------------------------
/docs_pt-br/js/custom.js:
--------------------------------------------------------------------------------
1 | $(window).load(function() {
2 | $('body').raptorize({
3 | 'enterOn' : 'konami-code'
4 | });
5 | });
--------------------------------------------------------------------------------
/docs_pt-br/js/jquery.raptorize.1.0.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Raptorize Plugin 1.0
3 | * www.ZURB.com/playground
4 | * Copyright 2010, ZURB
5 | * Free to use under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | */
8 |
9 |
10 | (function($) {
11 |
12 | $.fn.raptorize = function(options) {
13 |
14 | //Yo' defaults
15 | var defaults = {
16 | enterOn: 'click', //timer, konami-code, click
17 | delayTime: 5000 //time before raptor attacks on timer mode
18 | };
19 |
20 | //Extend those options
21 | var options = $.extend(defaults, options);
22 |
23 | return this.each(function() {
24 |
25 | var _this = $(this);
26 | var audioSupported = false;
27 | //Stupid Browser Checking which should be in jQuery Support
28 | if ($.browser.mozilla && $.browser.version.substr(0, 5) >= "1.9.2" || $.browser.webkit) {
29 | audioSupported = true;
30 | }
31 |
32 | //Raptor Vars
33 | var raptorImageMarkup = ''
34 | var raptorAudioMarkup = '';
35 | var locked = false;
36 |
37 | //Append Raptor and Style
38 | $('body').append(raptorImageMarkup);
39 | if(audioSupported) { $('body').append(raptorAudioMarkup); }
40 | var raptor = $('#elRaptor').css({
41 | "position":"fixed",
42 | "bottom": "-700px",
43 | "right" : "0",
44 | "display" : "block"
45 | })
46 |
47 | // Animating Code
48 | function init() {
49 | locked = true;
50 |
51 | //Sound Hilarity
52 | if(audioSupported) {
53 | function playSound() {
54 | document.getElementById('elRaptorShriek').play();
55 | }
56 | playSound();
57 | }
58 |
59 | // Movement Hilarity
60 | raptor.animate({
61 | "bottom" : "0"
62 | }, function() {
63 | $(this).animate({
64 | "bottom" : "-130px"
65 | }, 100, function() {
66 | var offset = (($(this).position().left)+400);
67 | $(this).delay(300).animate({
68 | "right" : offset
69 | }, 2200, function() {
70 | raptor = $('#elRaptor').css({
71 | "bottom": "-700px",
72 | "right" : "0"
73 | })
74 | locked = false;
75 | })
76 | });
77 | });
78 | }
79 |
80 |
81 | //Determine Entrance
82 | if(options.enterOn == 'timer') {
83 | setTimeout(init, options.delayTime);
84 | } else if(options.enterOn == 'click') {
85 | _this.bind('click', function(e) {
86 | e.preventDefault();
87 | if(!locked) {
88 | init();
89 | }
90 | })
91 | } else if(options.enterOn == 'konami-code'){
92 | var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
93 | $(window).bind("keydown.raptorz", function(e){
94 | kkeys.push( e.keyCode );
95 | if ( kkeys.toString().indexOf( konami ) >= 0 ) {
96 | init();
97 | kkeys = [];
98 | // $(window).unbind('keydown.raptorz');
99 | }
100 | }, true);
101 |
102 | }
103 |
104 | });//each call
105 | }//orbit plugin call
106 | })(jQuery);
107 |
108 |
--------------------------------------------------------------------------------
/docs_pt-br/js/raptor-sound.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/js/raptor-sound.mp3
--------------------------------------------------------------------------------
/docs_pt-br/js/raptor-sound.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/js/raptor-sound.ogg
--------------------------------------------------------------------------------
/docs_pt-br/js/raptor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/js/raptor.png
--------------------------------------------------------------------------------
/docs_pt-br/tutorial/aplicacoes-multi-conteiner/multi-app-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockersamples/101-tutorial/05be8bd9e9ecea7fdae60a5dffaf9f880d21b38b/docs_pt-br/tutorial/aplicacoes-multi-conteiner/multi-app-architecture.png
--------------------------------------------------------------------------------
/docs_pt-br/tutorial/atualizando-nossa-aplicacao/index.md:
--------------------------------------------------------------------------------
1 |
2 | Como uma pequena solicitação de funcionalidade, fomos acionados pela equipe de produto para que seja alterado
3 | o "texto vazio" quando não tivermos nenhum item da lista de tarefas. Eles
4 | gostariam de fazer a transição para o seguinte:
5 |
6 | > Sem tarefas ainda! Adicione uma acima!
7 |
8 | Simples, não? Vamos fazer essa mudança.
9 |
10 | ## Atualizando nosso código fonte
11 |
12 | 1. No arquivo `~/app/src/static/js/app.js` atualize a linha 56 para que o novo "texto vazio" seja utilizado. ([Dicas de edição de arquivos no PWD aqui](/dicas-pwd/#editando-arquivos))
13 |
14 | ```diff
15 | -