- server: A physical machine connected to the web
- service: A deployed program (e.g. GraphQL endpoint / REST endpoint)
- environment: The OS that a service runs in
- There was one environment on a server
- These environments were mutable
- They needed lots of maintenance (for security)
- This meant their environment was constantly changing
This causes a number of problems.
- How do we reproduce an environment that is constantly changing
- Our code works in CI but might fail when deployed (different environnments)
- An update/new package to the environment break our deployed service
Example:
== CI Run ==
Ubuntu 20.04
Node 12
Tests run fine
== Deployment ==
Ubuntu: 20.04
Node: 12
Tests fail
- A single environment could have many services
- Services could have conflicting environment dependencies (e.g. node 12 and node 14)
Example:
== Service A requirements ==
Chrome: 67
Node: 12
== Service B requirements ==
Chrome: 64 (!)
Node: 12
- If one of our services has a vulnerability, all services are vulnerable
- Malicious code on the server could attack all services
- What is to stop one service from accidentally breaking another (e.g. deleting files)
- A runtime for contained environments
- Each service gets its own evironment
- A single server can now run many environments
How it works:
- Images are created prior to deploy time
- These images can then be run on any machine with the Docker runtime
- A running image, is called a container
How this solves the above problems:
- Environments are now declarative
- They do not change over time
- Any change to an environment would be the creation of a new image
Here's an example Dockerfile which is used to create a docker image
# Specify OS
FROM ubuntu:12.04
# Install OS dependencies to image
RUN apt install chrome@75 node@14
# Copy files to image
COPY . /app
# Run command
CMD [ "node", "/app/index.js" ]
- Running an image on any machine will reap identical results
- The only variables are network and compute performance/capability
- Services are now contained
- Containers cannot communicate with other containers without explicit permission
- A vulnerable container will be an isolated incident