├── README.md
├── docker101-linux-dceu-1017.pdf
├── linux_tweet_app
├── Dockerfile
├── index-new.html
├── index-original-html
├── index.html
└── linux.png
├── part-1
└── README.md
├── part-2
└── README.md
└── part-3
└── README.md
/README.md:
--------------------------------------------------------------------------------
1 | # Docker 101 self-paced labs
2 |
3 | There are three parts this lab
4 |
5 | * [Part 1](https://github.com/mikegcoleman/docker101-linux/tree/master/part-1) deals with basic container management
6 | * [Part 2](https://github.com/mikegcoleman/docker101-linux/tree/master/part-2) covers the Docker file system and Docker volumes (including persistent data)
7 | * [Part 3](https://github.com/mikegcoleman/docker101-linux/tree/master/part-3) talks about orchestration with Swarm and how Docker handles networking
8 |
9 | There is also a PDF of the slides I use when I present this as a workshop.
10 |
--------------------------------------------------------------------------------
/docker101-linux-dceu-1017.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikegcoleman/docker101-linux/1ba9b3818d2e34469157aa941047e133c9f6ee27/docker101-linux-dceu-1017.pdf
--------------------------------------------------------------------------------
/linux_tweet_app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:latest
2 |
3 | COPY index.html /usr/share/nginx/html
4 | COPY linux.png /usr/share/nginx/html
5 |
6 | EXPOSE 80 443
7 |
8 | CMD ["nginx", "-g", "daemon off;"]
9 |
--------------------------------------------------------------------------------
/linux_tweet_app/index-new.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Docker 101!
34 |
35 |

36 |
37 | You've successfully deployed the Linux tweet app! Why not let the world know?
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/linux_tweet_app/index-original-html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Docker 101!
34 |
35 |

36 |
37 | You've successfully deployed the Linux tweet app! Why not let the world know?
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/linux_tweet_app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Docker 101!
34 |
35 |

36 |
37 | You've successfully deployed the Linux tweet app! Why not let the world know?
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/linux_tweet_app/linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikegcoleman/docker101-linux/1ba9b3818d2e34469157aa941047e133c9f6ee27/linux_tweet_app/linux.png
--------------------------------------------------------------------------------
/part-1/README.md:
--------------------------------------------------------------------------------
1 | # Lab 1: Docker 101 (Linux): Basic Docker Commands,Building Docker Images, and Accessing Local Files
2 |
3 | In this lab we'll take a look at some basic Docker commands and a simple build-ship-run workflow. We'll start by running some simple docker containers. Then we'll use a *Dockerfile* to build a custom app. Finally, we'll look at how to use bind mounts to modify a running container as you might if you were actively developing using Docker.
4 |
5 | > **Difficulty**: Beginner (assumes no familiarity with Docker)
6 |
7 | > **Time**: Approximately 30 minutes
8 |
9 | > **Tasks**:
10 | >
11 |
12 | > * [Task 0: Prerequisites](#Task_0)
13 | > * [Task 1: Run some simple Docker containers](#Task_1)
14 | > * [Task 2: Package and run a custom app using Docker](#Task_2)
15 | > * [Task 3: Modify a Running Website](#Task_3)
16 |
17 | ## Task 0: Prerequisites
18 |
19 | Before we start, you'll need to gain access to your Linux VM, clone a GitHub repo, and make sure you have a DockerID.
20 |
21 | ### Access your Linux VM
22 | 1. Visit [Play With Docker](https://hybrid.play-with-docker.com)
23 | 2. Click `Start Session`
24 | 2. On the left click `+ Add New Instance`
25 |
26 | All of the exercises in this lab will be performed in the console window on the right of the Play With Docker screen.
27 |
28 | ### Clone the Lab GitHub Repo
29 |
30 | Use the following command to clone the lab repo from GitHub.
31 |
32 | ```
33 | $ git clone https://github.com/dockersamples/linux_tweet_app
34 | Cloning into 'linux_tweet_app'...
35 | remote: Counting objects: 14, done.
36 | remote: Compressing objects: 100% (9/9), done.
37 | remote: Total 14 (delta 5), reused 14 (delta 5), pack-reused 0
38 | Unpacking objects: 100% (14/14), done.
39 | ```
40 |
41 | ### Make sure you have a DockerID
42 |
43 | If you do not have a DockerID (a free login used to access Docker Cloud, Docker Store, and Docker Hub), please visit [Docker Cloud](https://cloud.docker.com) to register for one.
44 |
45 | ## Task 1: Run some simple Docker containers
46 |
47 | There are different ways to use containers:
48 |
49 | 1. **To run a single task:** This could be a shell script or a custom app
50 | 2. **Interactively:** This connects you to the container similar to the way you SSH into a remote server
51 | 3. **In the background:** For long-running services like websites and databases
52 |
53 | In this section you'll try each of those options and see how Docker manages the workload.
54 |
55 | ### Run a single-task Alpine Linux container
56 |
57 | In this step we're going to start a new container and tell it to run the `hostname` command. The container will start, execute the `hostname` command, then exit.
58 |
59 | 1. Run the following command in your Linux console:
60 |
61 | ```
62 | $ docker container run alpine hostname
63 | Unable to find image 'alpine:latest' locally
64 | latest: Pulling from library/alpine
65 | 88286f41530e: Pull complete
66 | Digest: sha256:f006ecbb824d87947d0b51ab8488634bf69fe4094959d935c0c103f4820a417d
67 | Status: Downloaded newer image for alpine:latest
68 | 888e89a3b36b
69 | ```
70 |
71 | The output above shows that the `alpine:latest` image could not be found locally. When this happens, Docker automatically *pulls* it form Docker Hub.
72 |
73 | After the image is pulled, the container's hostname is displayed (`888e89a3b36b` in the example above).
74 |
75 | 2. Docker keeps a container running as long as the process it started inside the container is still running. In this case, the `hostname` process completes when the output is written, so the container exits. The Docker platform doesn't delete resources by default, so the container still exists in the `Exited` state.
76 |
77 | List all containers
78 |
79 | ```
80 | $ docker container ls --all
81 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
82 | 888e89a3b36b alpine "hostname" 50 seconds ago Exited (0) 49 seconds ago awesome_elion
83 | ```
84 |
85 | Notice that your Alpine Linux container is in the `Exited` state.
86 |
87 | > **Note:** The container ID *is* the hostname that the container displayed. In the example above it's `888e89a3b36b`
88 |
89 | Containers which do one task and then exit can be very useful. You could build a Docker image that executes a script to configure something. Anyone can execute that task just by running the container - they don't need the actual scripts or configuration information.
90 |
91 |
92 | ### Run an interactive Ubuntu container
93 |
94 | You can run a container based on a different version of Linux than is running on your Docker host.
95 |
96 | In the next example, we are going to run an Ubuntu Linux container on top of an Alpine Linux Docker host (Play With Docker uses Alpine Linux for its nodes).
97 |
98 | 1. Run a Docker container and access its shell.
99 |
100 | In this case we're giving the `docker container run` command three parameters:
101 |
102 | * `--interactive` says you want an interactive session
103 | * `--tty` allocates a psuedo-tty
104 | * `--rm` tells Docker to go ahead and remove the container when it's done executing
105 |
106 | The first two parameters allow you to interact with the Docker container.
107 |
108 | We're also telling the container to run `bash` as its main process (PID 1).
109 |
110 | ```
111 | $ docker container run --interactive --tty --rm ubuntu bash
112 | ```
113 |
114 | When the container starts you'll drop into the bash shell with the default prompt `root@:/#`. Docker has attached to the shell in the container, relaying input and output between your local session and the shell session in the container.
115 |
116 | 2. Run some commands in the container:
117 |
118 | - `ls /` - lists the contents of the root directory
119 | - `ps aux` - shows all running processes in the container.
120 | - `cat /etc/issue` - shows which Linux distro the container is running, in this case Ubuntu 16.04 LTS
121 |
122 | 3. Type `exit` to leave the shell session. This will terminate the `bash` process, causing your container to exit.
123 |
124 | > **Note:** As we used the `--rm` flag when we started the container, Docker removed that container when it stopped. This means if you run another `docker container ls --all` you won't see the Ubuntu container.
125 |
126 | 4. For fun, let's check the version of our host VM
127 |
128 | ```
129 | $ cat /etc/issue
130 |
131 | Welcome to Alpine Linux 3.6
132 | Kernel \r on an \m (\l)
133 | ```
134 |
135 | Notice that our host VM is Alpine, yet we were able to run an Ubuntu container. As previously mentioned, the distribution of Linux in the container does not need to match the distribution of Linux running on the Docker host.
136 |
137 | However, Linux containers require the Docker host to be running a Linux kernel. For example, Linux containers cannot run directly on Windows Docker hosts. The same is true of Windows containers - they need to run on a Docker host with a Windows kernel.
138 |
139 | Interactive containers are useful when you are putting together your own image. You can run a container and verify all the steps you need to deploy your app, and capture them in a Dockerfile.
140 |
141 | > **Note:** You *can* [commit](https://docs.docker.com/engine/reference/commandline/commit/) a container to make an image from it - but you should avoid that wherever possible. It's much better to use a repeatable [Dockerfile](https://docs.docker.com/engine/reference/builder/) to build your image. You'll see that shortly.
142 |
143 |
144 | ### Run a background MySQL container
145 |
146 | Background containers are how you'll run most applications. Here's a simple example using MySQL.
147 |
148 | 1. Let's run MySQL in the background container using the `--detach` flag. We'll also use the `--name` flag to name the running container `mydb`.
149 |
150 | We'll also use an environment variable (`-e`) to set the root password (NOTE: This should never be done in production):
151 |
152 | ```
153 | $ docker container run \
154 | --detach \
155 | --name mydb \
156 | -e MYSQL_ROOT_PASSWORD=my-secret-pw \
157 | mysql:latest
158 |
159 | Unable to find image 'mysql:latest' locallylatest: Pulling from library/mysql
160 | aa18ad1a0d33: Pull complete
161 | fdb8d83dece3: Pull complete
162 |
163 | 315e21657aa4: Pull complete
164 | Digest: sha256:0dc3dacb751ef46a6647234abdec2d47400f0dfbe77ab490b02bffdae57846ed
165 | Status: Downloaded newer image for mysql:latest
166 | 41d6157c9f7d1529a6c922acb8167ca66f167119df0fe3d86964db6c0d7ba4e0
167 | ```
168 |
169 | Once again, the image we requested was not available locally, so Docker pulled it from Docker Hub.
170 |
171 | As long as the MySQL process is running, Docker will keep the container running in the background.
172 |
173 | 2. List running containers
174 |
175 | ```
176 | $ docker container ls
177 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
178 | 3f4e8da0caf7 mysql:latest "docker-entrypoint..." 52 seconds ago Up 51 seconds 3306/tcp mydb
179 | ```
180 |
181 | Notice your container is running
182 |
183 | 3. You can check what's happening in your containers by using a couple of built-in Docker commands: `docker container logs` and `docker container top`
184 |
185 | ```
186 | $ docker container logs mydb
187 |