1) Specify a base image
2) Run some commands to install additional programs
3) Specify a command to run on container startup
Eg, for running redis server, create a file named Dockerfile
#Use a base image
FROM alpine
#Manage dependencies (apk depends on alpine)
RUN apk add --update redis
#Startup command (note the space after CMD)
CMD ["redis-server"]
Build the image from the directory containing Dockerfile
docker build . (or) docker build -f [Custom Dockerfile Name] . #if using another name for Dockerfile # On successful build, you ll see the image idOr, get the image id
docker imagesRun the image
docker run [IMAGE_ID]
If you want to have a name for your image, use -t while docker build. The following naming convention is widely used for docker projects:
docker build -t [DOCKER_ID]/[IMAGE_NAME]:[VERSION_TAG] . docker run senesence/redis #if the version tag is not mentioned, :latest will be used if available
To remove a built image
docker rmi [IMAGE_NAME]To rename a built image
docker tag [OLD_IMAGE_NAME] [NEW_IMAGE_NAME] docker rmi [OLD_IMAGE_NAME]To push images to docker hub
docker login --username=[USERNAME] #first time docker push [DOCKER_ID]/[REPOSITORY_NAME]:[VERSION_TAG] #To push, image name should be in above formatTo pull from docker hub
docker pull [DOCKER_ID]/[REPOSITORY_NAME]:[VERSION_TAG]To save an image into a tar archieve
docker save [IMAGE_NAME] > [ARCHIEVE_NAME].tarTo load the image in different computer
docker load --input [ARCHIEVE_NAME].tar #This will place a copy of that image locally docker images
Sometimes, we load an image in shell, make some changes to file system and generate a new image. To do this,
docker run -it alpine sh /@: apt add --update redisOpen new terminal, and get the container id and commit (note the single and double quotes and space after CMD)
docker ps docker commit -c 'CMD ["START COMMAND"]' [IMAGE_NAME]This will create a new image of the container. However, it is always recommended to use the Dockerfile as we can recreate the build in different machine.
In real projects, we ll have project files to be run on container. We want to copy those files to FS and change the working directory to the directory containing files
project dir:
main.py
from flask import Flask
app = Flask(__name__)
app.debug=True
@app.route('/')
def index():
return "<h1>Hi</h1>"
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8000)
requirements.txt
flask==1.0.2Dockerfile
#In Docker, tag alpine referes to light weight versions (~100MB) FROM python:3.7.1-alpine3.7 #Set working directory. If path does not exist, it is created WORKDIR /home #Copy files from current host directory to current working directory (/home) COPY ./ ./ #Install flask RUN pip install -r requirements.txt #run script CMD ["python","main.py"]Build Dockerfile
docker build -t senesence/flask .Note that flask runs on port 8000 in the container.
Host machine port need not be same as container port
The port mapping should be explicitly specified during docker run
docker run -p [HOST_PORT]:[CONTAINER_PORT] senesence/flaskFor the above example, if we want to post the website on port 5000, for flask container on port 8000
docker run -p 5000:8000 senesence/flaskOpen browser and hit
localhost:5000NOTE: Editing files within container are not saved once container is exited! Copy is usually used for creating production images
Most often, we dont want to copy but have folders in sync between container and host machine
To do this, we use the -v option on docker run
Dockerfile (This time, We specify working dir on run time)
FROM python #(Full version ~ 900MB) #Install vim and flask RUN apt-get update RUN apt-get -y install vim #-y is important to make installation not prompt for keyboard input RUN pip install flask==1.0.2 #run script CMD ["bash"]Run -v [HOST_DIR]:[CONTAINER_DIR] -w [CONTAINER_WORK_DIR]
docker run -it -p 8080:8000 -v $PWD:/home -w /home senesence/flask:mount bash
Now changing anytyhing under /home in container will be reflected in the host machine (or vice versa)
IMPORTANT:
Directories are not copied but just referenced. Useful while developing and for big data
Creating new files from within container will set owner as root. Therefore, have atom running on host machine to edit, and just use container for execution.
For production code, we however need to copy the code into the container
Using -v without HOST_DIR
Suppose some dependencies (say /home/dep) were installed inside the /home dir of container while building. And we dont want them to be overriden in the container. In this case, we want to sync directories leaving out a particular dir in contaioner:
docker run -v /home/dep -v [HOST_DIR]:/home [IMAGE_NAME] bash