- Clone this reposisitory locally
- Install & run Docker for mac
Software containerization is named as such because it is analogous to shipping containers. The conformity of software containers greatly simplifies the complexity of running, sharing & deploying code. Specifically the technology provides the following benefits:
- Interoperable: guarantees that a container that runs on a developer's computer will behave the same on a coworker's machine or a server in the cloud
- Isolated: each container can manage its own dependencies making it simple to deploy multiple on a single machine to efficiently use all resources
- Standardized: regardless of what is running the process for increasing resources, viewing logs, or getting command line access are identical
Although other software container tools exist the popularity and adoption of Docker has made it fairly synonymous with containers.
The two main reasons for the popularity are that they are lightweight and easy to build.
Previous tools such as virtualization (think cloud servers) create an independent and complete machine. In other words it exactly mimics installing an OS on bare-metal.
Containers on the other hand rely on the kernal of the host operating system which makes them smaller and therefore faster to create. The Docker Daemon in charge of running containers insures interoperability that the container will work so long as it is running.
The standard way to define what will be inside & run within a container is the Dockerfile.
Although not required, a file named Dockerfile is a standard convention.
It contains simple instructions to copy & manipulate files and typically ends with an instruction to run them when the container starts.
A Docker image is the built by executing the instructions of a Dockerfile. An image vs. container is analogous to the software installed on your disk and the container is the running software.
The other important feature of images is the concept of layering. Each command that Docker executes in your Dockerfile creates a new layer. Layers are tranferrable, excutable, and cached so that subsequent builds execute more quickly. The final layer that is output from the build process are tagged and shared to make it easy to build other images from that layer.
The following exercises will use a popular web server called NGINX to launch a sample personal website and teach the following:
- Creating Dockerfiles
- Building images
- Starting containers
- Operating running containers
- Using docker compose
All instructions intend to be executed from the terminal in the directory of this repository
The very first line in a Dockerfile is the FROM command which establishes the base layer of your image
- Create a new file
Dockerfileand addFROM nginxto the first line and save it - Run
docker build .which tells Docker to buildDockerfile(default filename) in the current directory, chosen by the. - Tag your final layer with
docker build -t mysite .
The COPY command is used to add files into the image
Note: NGINX serves static content from /usr/share/nginx/html/
- Add
COPY index.html /usr/share/nginx/html/to the end of the Dockerfile - Add
COPY style.css /usr/share/nginx/html/to the end of the Dockerfile - Rebuild your image
docker build -t mysite .
run is the command used to start a container from an image
Note: The NGINX process runs on port 80 of the container
- start the container
docker run mysite - The container starts, and some logs from the nginx service will output
- There are a couple of problems with the first run:
- There is no way to access the web server on the container from your browser
- Your container doesn't have a consistent name, container ids can always be used but names are easier to remember
- The container is running in the foreground and command line has been taken
- Stop the container by typing
ctrl+c - Start the container in the background, bind your local port 8080 to it, and give it a name
docker run -d -p 8080:80 --name mysite mysite-dstarts the container as a background process-p 8080:80binds your local port 8080 -> port 80 on the container--name mysitenames your running container with a user defined label
- Visit your website at http://localhost:8080
- Run
docker psto display your containers statistics - From here you can observe if your container is running and other useful info
- Run
docker logs -f mysiteto view the existing logs and follow the output - Refresh your browser or make an additional request to http://localhost:8080
- Observe the requests that were made to root and the style sheet it loaded
- Note that without
-fthe output will only display the existing logs - Stop following the logs by typing
ctrl+c
- Run
docker exec mysite echo "hello from the container"to execute an echo on the container - For more flexible access to the container it is typical to get an interactive bash shell with
docker exec -it mysite bash - Command breakdown:
docker execis to execute commands on the container-itgives an pseudo terminal and keeps standard input openmysitespecifies the containerbashis the command to execute
- Access the static directory
cd /usr/share/nginx/html/ - Use the following command to replace the generic firstname in the index with your own:
- Change the
YourNamestring below sed -i s#@FirstName#YourName#g index.html
- Change the
- Refresh your browser to see the changes take effect immmediately
- type
ctlr+dto exit the containers shell
- Run
docker stop mysiteto stop the container - Attempting to create a new container named mysite will result in an error
docker run -d -p 8080:80 --name mysite mysite - See stopped containers by running
docker ps -a - The
mysitecontainer and your previous unnamed containers will be listed - Remove them using the name or id
docker rm mysite otherContainerId
By adding the --rm flag to the docker run command a stopped container will automatically be removed
docker run -d -p 8080:80 --name mysite --rm mysite- Stop the container:
docker stop mysite - Observe that the container is not stopped
docker ps -a
Sometimes it is useful to add files to a container without adding them into the image.
This technique known as mounting can be accomplished with the -v argument to the run command
docker run -d -p 8080:80 --name mysite --rm -v $(pwd)/docker-logo-vector.svg:/usr/share/nginx/html/logo.svg mysite- Browse to http://localhost:8080/logo.svg
- Stop the container
docker stop mysite
When a container starts it is instructed to run the entry point or command.
In order to replace that existing command simply add it to the end of docker run
- Display nginx command line help:
docker run -p 8080:80 --name mysite --rm mysite nginx -h - Note that the argument to run the process in the background (
-d) is omitted to view the logs
Making it easy to update the names in the personal website allows others to easily use the image
As previously mentioned when a container starts it runs a command to kick things off.
In the case of NGINX and our sample personal website the default start command is nginx -g 'daemon off;'
Until now the Dockerfile took advantage of this default inherited from the nginx base image.
This section teaches how to replace the default command to allow users to customize the personal website.
CMDis the Dockerfile directive used to set the start command- Add
COPY startup.sh .to addstartup.shto the image - Add
CMD ./startup.shto the end of your dockerfile, nowstartup.shwill run when the container starts. - This bash script will:
- optionally replace the sample values in the personal website based on environment variables
- delegate execution to nginx at the end
- Rebuild the image
docker build -t mysite .
Setting environment variables using the docker run command is a common way to customize a container.
- The
-eflag is used to set environment variables, for example-e "KEY=VALUE" - Modify the example command below with your personal information:
docker run -d -p 8080:80 --name mysite --rm -e "FIRSTNAME=Asaf" -e "LASTNAME=Peleg" -e "EMAILHANDLE=asafpelegcodes" -e "EMAILHOST=gmail.com" mysite
- Visit http://localhost:8080 to see your personalized website
- Stop the container with
docker stop mysite
As you have seen, Docker commands can get fairly complex and lengthy.
The solution to this problem is the Docker compose file, whose standard filename convention is docker-compose.yaml.
The compose file is yaml configuration which docker essentially translates into the arguments for one or more docker run executions.
docker compose also has equivalencies to most of the regular docker commands as you will see below.
The included compose file mimics the docker run command in the previous exercise but needs small changes.
- Open
docker-compose.yaml - Take note of:
- The build context specifying where the images Dockerfile is located
- The port mapping that forwards localhost:8080 -> port 80 of the container
- The list of environment variables that are set to empty
- Set each environment to an appropriate value by typing a string on the right hand of the equals sign
- To execute the compose file run
docker compose up -d - Visit http://localhost:8080
- Check your containers status with
docker compose ps - Check your containers logs with
docker compose logs - Execute commands on your containers with
docker compose exec mysite echo hello - To tear everything down run
docker compose down
Docker's public registry for images contains endless images to use or build from.
Anyone can upload images but the most common ones are those considered "Docker Official Images".
This curated list of images can easily be distinguished by the tag since they have no namespace.
Examples include nginx, mysql, ubuntu, java, python, etc.
These official images are an excellent building blocks for creating custom images but only represent a minute amount of all the images available.