Skip to content

Commit 216f105

Browse files
committed
Initial revision
0 parents  commit 216f105

File tree

14 files changed

+503
-0
lines changed

14 files changed

+503
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
spring-example/spring-app/.project
3+
4+
spring-example/spring-app/.classpath

README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# An introduction to Docker
2+
3+
Supplemental materials and reference guide for the Introduction to Docker presentation.
4+
5+
## Installing Docker
6+
7+
Mac and Windows users will need to install the Docker Toolbox to run and control containers (download for [Windows](https://docs.docker.com/engine/installation/windows/) or [Mac OS](https://docs.docker.com/engine/installation/mac/)).
8+
9+
Linux users can [install Docker directly](https://docs.docker.com/engine/installation/linux/) on various distributions.
10+
11+
##### A note for Mac and Windows users
12+
While you can't run Docker containers *directly* on your Mac or Windows machine, you can manage and control them as though they were. Docker Toolbox comes with a Mac and Windows native version of the `docker` command that knows how to proxy into the Docker Machine and control containers executing inside that "machine." (This was previously not possible on Windows with boot2docker; Docker Machine fixed this limitation.)
13+
14+
*Why should I care?* This feature has the effect of letting native Mac and Windows processes directly control and manage Docker containers. This is especially useful if you're developing code in which your build scripts or integration tests expect to be able to build, start and run a container. Of course, keep in mind that your container-to-host port forwarding will not expose the container's port to your Mac or Windows, but only to your Docker Machine VM. If you need to access your container's ports directly from Mac OS or Windows, you'll need to forward those same ports from the Docker Machine guest OS to your host. (Sound of head exploding, here.)
15+
16+
## Docker Command Reference
17+
18+
A brief refresher on building images and managing containers.
19+
20+
#### Build a Docker image from a Dockerfile
21+
`docker build -t <tag-name> <directory>` where `<tag-name>` is the name that will be assigned to this image and `<directory>` is the path to the directory containing the Dockerfile.
22+
23+
* Docker will download any dependent images and build your image according to the Dockerfile. If all goes well, the last line produced by the command should read `Successfully built 351e2c3e7c5c` (your hash will vary).
24+
25+
#### Listing images stored locally
26+
`docker images` will display all the images built on your machine. It will produce output like:
27+
```
28+
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
29+
my-example-image latest 0db6c7503383 7 seconds ago 227.6 MB
30+
ubuntu latest 6cc0fc2a5ee3 3 weeks ago 187.9 MB
31+
```
32+
33+
#### Create a container from an existing image
34+
`docker create -p <host-port>:<container-port> <image-name>` will create a container from the image tagged `<image-name>` where `<container-port` is an exposed port on the container and `<host-port>` is the port on the host machine that it should be mapped to. For example, if our container was running a web server on port 80 and we wanted to access that server through port 8080 on our host, we'd provide the argument `-p 8080:80`.
35+
36+
* By default, Docker will assign a nonsensical (sometimes comical) name to your container, like `lactating_monkey`. You'll likely wish to refer to this container by name in the future and you can assign your own name using the `--name=` argument on the command line. For example, `docker create my-example-image --name=webserver`.
37+
38+
#### Listing containers
39+
* `docker ps -a` will show all containers (in any state) on the local machine.
40+
* `docker ps` will show only the running containers.
41+
42+
Both commands produce output like:
43+
```
44+
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
45+
fb6bcff347c8 my-example-image "nginx" 7 minutes ago Up 7 minutes 0.0.0.0:8082->80/tcp webserver
46+
```
47+
48+
#### Starting a container
49+
`docker run <container-name>` will start the container named `<container-name>`.
50+
51+
* Had we not used the `--name` argument in the `docker create` command we would have to refer to this container using either a) the nonsensical name auto-assigned to it (`lactating_monkey`) or b) the container ID hash (something like `fb6bcff347c8`).
52+
53+
#### Stopping a container
54+
`docker stop <container-name>` will stop the running container named `<container-name>`.
55+
56+
* Like with `docker start` you may substitute the container name with an ID hash prefix if you wish.
57+
58+
#### Helpful cleanup commands
59+
Typically one does not usually clean and rebuild everything, but when experimenting its often helpful to be able to return to a clean state.
60+
* `docker stop $(docker ps -q)` to stop all running containers on your machine.
61+
* `docker rm $(docker ps -aq)` to delete all containers on your machine.
62+
* `docker rmi $(docker images -q)` to blow away all images on your machine (works only if no containers exist that were created from the images; best to execute after blowing away all containers).
63+
64+
#### A note about hashes
65+
Whenever referring to an image or container by its ID hash (i.e., `fb6bcff347c8`), you may supply the shortest prefix that remains unambiguous. For example, rather than `docker stop fb6bcff347c8` you could use `docker stop fb6` provided no other container IDs began with `fb6`. In fact, oftentimes a single letter will suffice: `docker stop f`
66+
67+
## Examples
68+
To run these examples, you'll need a shell inside the Docker Machine and the contents of this repository. Get started by:
69+
70+
1. Start a shell inside your Docker Machine by using the Docker Quickstart Terminal app that was installed on Mac and Windows (Linux users can skip this step). See the "Docker Quickstart Terminal" section of the [Windows](https://docs.docker.com/engine/installation/windows/) and [Mac OS](https://docs.docker.com/engine/installation/mac/) install guide for details.
71+
2. Clone this repository using the git command `git clone http://github.com/TBD`
72+
73+
As you work through these examples be sure to read, understand, and follow all safety rules that came with your power tools. Also, take a look at the example Dockerfiles. They're commented to explain what's happening in each step.
74+
75+
#### Example 1: Static Web Server
76+
In this example, we'll create a Docker container based on the Ubuntu distribution, install the Nginx server on it and have it serve a single HTML document (one that will be "baked" into the Docker image).
77+
78+
1. Enter the example directory: `cd webserver-example`
79+
2. Build a Docker image from the Dockerfile using `docker build -t example/nginx-img .` Upon success, this will have create a new Docker image called `example/nginx-img`.
80+
3. Create a container from the newly built image and forward port 80 of the container to port 8080 of our host: `docker create -p 8080:80 --name=webserver example/nginx-img`
81+
4. Use `docker start webserver` to run the container.
82+
83+
Then...
84+
85+
1. See it in action with `curl localhost:8080` (or enter this URL in a browser). You should see the HTML contents of `index.html`.
86+
2. When you're satisfied with your fine work, stop the container with `docker stop webserver`. If you wish, you can destroy the container using `docker rm webserver` and delete the image used to create it with `docker rmi example/nginx-img`
87+
88+
#### Example 2: Volume Web Server
89+
Example 1 illustrated how we could set up a web server in Docker but this was clearly limited in that it could only serve files that were baked into the container's image. This example solves that limitation by linking a portion of the host's filesystem to the container (called a "volume"). This will enable us to add or modify the contents served by Nginx without having to rebuild (or even stop) the container.
90+
91+
1. Enter the example directory: `cd webserver-volume-example`
92+
2. Build the image using `docker build -t example/nginx-volume-img .`
93+
3. Create a container from this image, `docker create -p 8080:80 --name=volumeserver -v /path/to/example/www:/var/www example/nginx-volume-img` where `path/to/example/www` is the absolute path to the `www` directory inside this example. (Sorry Charlie, you can't use a relative path here.)
94+
4. Start the container `docker start volumeserver`
95+
96+
Then...
97+
1. `curl localhost:8080` to see the HTML contents of `www/index.html` returned.
98+
2. Try modifying the contents of `www/index.html` and making the same `curl`
99+
request (you should see your changes reflected in the output)
100+
3. Try adding new files to the `www/` directory. For example,
101+
`echo '<html>Goodbye Cruel World</html>' > www/goodbye.html` then request `curl localhost:8080/goodbye.html`
102+
4. Stop the container using `docker stop volumeserver` and, if desired, blow away the container and image. You remember how to do that, right? (Hint: `docker rm` and `docker rmi`)
103+
104+
#### Example 3: Spring Boot Server
105+
Creates a Docker container running a trivial Spring Boot web application that responds to simple RESTful requests.
106+
107+
1. Enter the example directory: `cd spring-example`
108+
2. Build the Docker image with `docker build -t example/spring-img .`
109+
3. Create a container from this image using `docker create -p 8080:8080 --name springserver example/spring-img`
110+
4. Start the container: `docker start springserver`
111+
112+
Then...
113+
114+
1. In another terminal window, `curl localhost:8080` to see the Spring web app produce the output "Hello World!".
115+
2. Stop the container using `docker stop springserver`
116+
117+
#### Example 4: Linking Spring Boot to Redis
118+
In this example, the goal is to have our Spring Boot server read and write entries in a Redis cache that's operating in a separate container. Docker provides the concept of *container linking* for this purpose; when two containers are linked, Docker will write a host entry into the `/etc/hosts` file of the target container providing the IP address of the linked container.
119+
120+
1. Enter the Redis example directory: `cd redis-example`
121+
2. Build the Redis image using `docker build -t example/redis-img .`
122+
3. Create a container instance from the newly generated image with `docker create --name redis example/redis-img`
123+
4. Start the container with `docker start redis`. Note that we're not exposing any of the container's ports to the host operating system. Nevertheless, the Redis port (6379) will be accessible from the Spring Boot server which we will link to it.
124+
5. Return to the Spring Boot example: `cd ../spring-example`
125+
6. Since the Spring Boot example image has already been created, we don't need to re-run those commands. (And if you do, you'll find that Docker complains that the `example/spring-img` and `springserver` names are already in use.)
126+
7. Start the Spring Boot server and link it to the Redis container (already running) using `docker run --link redis:redishost -p 8080:8080 --name springredis example/spring-img`. This syntax should look pretty familiar at this point, with the addition of the `--link` switch. Link takes the name of a *running* container and the hostname to which its IP address should be assigned. In this case, our Redis container is going to be linked into the `springserver` container using the hostname `redishost` (as previously noted, Docker accomplishes this by writing a record into the `/etc/hosts` file like `redishost 192.168.1.90`). Now, our Redis-linked Spring Boot container can reach the Redis container by referring to it's hostname `redishost`. In fact, we could open a shell in the `springredis` container and `ping redishost`.

redis-example/Dockerfile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# ------------------------------------------------------------------------------
2+
# Specify the image from which we inherit: an Ubuntu distribution in this case.
3+
# Note that every Dockerfile _must_ begin with a 'FROM' command.
4+
#
5+
# What are my choices? Search the Docker Hub for available base images:
6+
# https://hub.docker.com
7+
# ------------------------------------------------------------------------------
8+
FROM ubuntu:latest
9+
10+
11+
# ------------------------------------------------------------------------------
12+
# Whose fault is this? Assigning blame is very important. :)
13+
# ------------------------------------------------------------------------------
14+
15+
16+
17+
# ------------------------------------------------------------------------------
18+
# Install the Redis server software onto the image
19+
# ------------------------------------------------------------------------------
20+
RUN apt-get update
21+
RUN apt-get install -y redis-server
22+
23+
24+
# ------------------------------------------------------------------------------
25+
# Expose the port that Redis runs on
26+
# ------------------------------------------------------------------------------
27+
EXPOSE 6379
28+
29+
30+
# ------------------------------------------------------------------------------
31+
# Start the Redis server in the container
32+
# ------------------------------------------------------------------------------
33+
CMD ["/usr/bin/redis-server"]

spring-example/Dockerfile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# ------------------------------------------------------------------------------
2+
# In this example, we're starting with the Java:8 base image. Of course, we
3+
# could start with a basic Linux distro like Ubuntu and run commands to install
4+
# a JRE, but this simplifies our life.
5+
#
6+
# Search https://hub.docker.com for alternatives.
7+
# ------------------------------------------------------------------------------
8+
FROM java:8
9+
10+
11+
# ------------------------------------------------------------------------------
12+
# Base image comes with Java, but we'll need Maven to compile our app.
13+
# ------------------------------------------------------------------------------
14+
RUN apt-get update
15+
RUN apt-get install -y maven
16+
17+
18+
# ------------------------------------------------------------------------------
19+
# Specify the current working directory (like cd in a shell). All commands
20+
# executed subsequent to this will execute from within the /code directory.
21+
#
22+
# Not strictly necessary as we could always specify absolute paths instead.
23+
# ------------------------------------------------------------------------------
24+
WORKDIR /code
25+
26+
27+
# ------------------------------------------------------------------------------
28+
# For simplicity, we're adding the source code of our webapp project into the
29+
# image and compiling it with Maven. While perfectly legal, a better approach
30+
# might be to pre-compile the app (perhaps with a CI system) and simply ADD the
31+
# compiled JAR, WAR or EAR to your image.
32+
#
33+
# Running 'mvn package' here creates a target/ subdirectory and places the
34+
# compiled JAR (spring-example-1.0.0.jar) into it.
35+
# ------------------------------------------------------------------------------
36+
ADD spring-app /code
37+
RUN mvn package -DskipTests=true
38+
39+
40+
# ------------------------------------------------------------------------------
41+
# Expose the server's port (8080)
42+
# ------------------------------------------------------------------------------
43+
EXPOSE 8080
44+
45+
46+
# ------------------------------------------------------------------------------
47+
# Start the server when the container starts
48+
# ------------------------------------------------------------------------------
49+
CMD /usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar target/spring-example-1.0.0.jar

spring-example/spring-app/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target/
2+
.gradle/
3+
.settings/

spring-example/spring-app/pom.xml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.defano</groupId>
7+
<artifactId>spring-example</artifactId>
8+
<version>1.0.0</version>
9+
10+
<parent>
11+
<groupId>org.springframework.boot</groupId>
12+
<artifactId>spring-boot-starter-parent</artifactId>
13+
<version>1.3.2.RELEASE</version>
14+
</parent>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter-web</artifactId>
20+
</dependency>
21+
<dependency>
22+
<groupId>org.springframework.boot</groupId>
23+
<artifactId>spring-boot-starter-actuator</artifactId>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.springframework.boot</groupId>
27+
<artifactId>spring-boot-starter-test</artifactId>
28+
<scope>test</scope>
29+
</dependency>
30+
<dependency>
31+
<groupId>redis.clients</groupId>
32+
<artifactId>jedis</artifactId>
33+
<type>jar</type>
34+
<scope>compile</scope>
35+
</dependency>
36+
</dependencies>
37+
38+
<properties>
39+
<java.version>1.8</java.version>
40+
</properties>
41+
42+
<build>
43+
<plugins>
44+
<plugin>
45+
<groupId>org.springframework.boot</groupId>
46+
<artifactId>spring-boot-maven-plugin</artifactId>
47+
</plugin>
48+
<plugin>
49+
<artifactId>maven-failsafe-plugin</artifactId>
50+
<executions>
51+
<execution>
52+
<goals>
53+
<goal>integration-test</goal>
54+
<goal>verify</goal>
55+
</goals>
56+
</execution>
57+
</executions>
58+
</plugin>
59+
</plugins>
60+
</build>
61+
62+
</project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.defano.spring;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class Application {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(Application.class, args);
11+
}
12+
13+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.defano.spring;
2+
3+
import javax.annotation.PostConstruct;
4+
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
import org.springframework.web.bind.annotation.RequestMethod;
7+
import org.springframework.web.bind.annotation.RequestParam;
8+
import org.springframework.web.bind.annotation.RestController;
9+
10+
import redis.clients.jedis.Jedis;
11+
12+
@RestController
13+
public class RedisCacheController {
14+
15+
private Jedis jedis;
16+
17+
@PostConstruct
18+
public void initJedis () {
19+
// 'redishost' is the host name of the Redis server; we will use Docker linking to define this host in /etc/hosts
20+
this.jedis = new Jedis("redishost");
21+
}
22+
23+
@RequestMapping("/")
24+
public String index() {
25+
return "Hello world!\n";
26+
}
27+
28+
@RequestMapping(value="/set", method=RequestMethod.GET)
29+
public String set (@RequestParam String key, @RequestParam String value) {
30+
jedis.set(key, value);
31+
return "Set: " + key + "=" + value + "\n";
32+
}
33+
34+
@RequestMapping(value="/get", method=RequestMethod.GET)
35+
public String get (@RequestParam String key) {
36+
String value = jedis.get(key);
37+
return "Get: " + key + "=" + value + "\n";
38+
}
39+
}

0 commit comments

Comments
 (0)