Docker 入门笔记 2 - 初步使用
本文内容参考自 https://docs.docker.com/get-started/part2/
Docker 基本架构
Docker 使用 client-server架构。
- Docker client 运行docker命令
- Docker daemon 负责构建,运行,以及发布Docker容器,并管理其他docker对象,包括网络及volumes。
- Docker Registry 存储image的仓库
三者可以位于不同主机,通常使用Docker Hub作为docker仓库。
client通过脚本或者CLI command 发送REST API与daemon之间进行交互(本机IPC用UNIX domain sockets, 否则使用network interface)。其他Docker应用也可以使用底层API与Deamon通信
常见工作过程:
sequenceDiagram
client->>Daemon : build image
client->>Registry: push image to daemon
client->>Registry: pull image to daemon
client->>Daemon : run image in a container
下面通过一个实例体会一下Docker的使用过程
申请docker hub用户
为了后面使用方便,先申请一个docker hub用户,网址如下:
创建一个python 运行环境image
使用Dockerfile定义一个容器
Dockerfile 定义容器内的环境中包含的内容。在这个环境中虚拟化像网络接口和磁盘驱动器这样的资源,这个环境与系统的其他部分是隔离的,所以你必须把端口映射到外部世界,并且明确你要“复制”到哪个文件那个环境。
1. 新建一个试验目录,并创建如下文件
pythonRT
├── app.py
├── Dockerfile
└── requirements.txt
文件内容如下:
- Dockerfile
# 使用一个官方的 python 运行环境 作为parent image
FROM python:2.7-slim
# 设定工作目录 /app
WORKDIR /app
# copy当前目录内容至工作目录
ADD . /app
# 用python pip 安装requirements.txt 中指定的package
# 要说明的是,这些python pakcage只会在容器内安装, 并不需要在host上安装python 或者 相关的package
RUN pip install --trusted-host pypi.python.org --verbose -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
如果通过代理上网, 可能需要为docker指定代理地址。
ENV http_proxy host:port
ENV https_proxy host:port
- requirements.txt
Flask
Redis
里面指定了两个package,Python轻量Web框架Flask 和 key-value存储系统Redis
- app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
2. 运行build命令来创建一个Docker image
# -t 添加一个tag 叫做 friendlyhello
docker build -t friendlyhello .
执行过程中可能会遇到无法解析 “pypi.python.org” 域名的错误。解决方案参考如下连接。Specify DNS servers for Docker
查看创建的image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python 2.7-slim 4fd30fc83117 6 days ago 138MB
3. 运行app
#-p 用于映射主机端口4000 与 容器开放端口 80
#-d 指定容器以deamon形式运行
docker run -d -p 4000:80 friendlyhello
可以使用浏览器或者 curl命令 进行测试
curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> 6179e26c02ed<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
查看,结束运行中的容器
$docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6179e26c02ed friendlyhello "python app.py" 6 minutes ago Up 6 minutes 0.0.0.0:4000->80/tcp tender_archimedes
$ docker container stop 6179e26c02ed
6179e26c02ed
共享image
记得之前提到过的docker hub吧, 接下来我们通过docker push把image提交到仓库来共享这个image。
首先登录docker hub。
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: misterchi
Password:
Login Succeeded
之前创建image是我们指定过一个tag “friendlyhello” 为了更好的识别,重新给image一个与repository相关联的tag。
#语法:docker tag image username/repository:tag
docker tag friendlyhello misterchi/repositorytest:hello
再次查看image列表,可以看见同一个image被打上了不同的tag
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest 0501a8fe40aa About an hour ago 148MB
misterchi/repositorytest hello 0501a8fe40aa About an hour ago 148MB
python 2.7-slim 4fd30fc83117 7 days ago 138MB
hello-world latest f2a91732366c 4 weeks ago 1.85kB
上传image
docker push misterchi/repositorytest:hello
成功后,登录docker hub页面可以看到上传的image
从 Registry Pull 并运行image
#如果本地没有就会从remot pull image
#如果不使用 :tag 则会默认添加 :latest作为tag
docker run -p 4000:80 misterchi/repositorytest:hello
常见命令总结
docker build -t friendlyname . # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyname # Run "friendlyname" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyname # Same thing, but in detached mode
docker container ls # List all running containers
docker container ls -a # List all containers, even those not running
docker container stop <hash> # Gracefully stop the specified container
docker container kill <hash> # Force shutdown of the specified container
docker container rm <hash> # Remove specified container from this machine
docker container rm $(docker container ls -a -q) # Remove all containers
docker image ls -a # List all images on this machine
docker image rm <image id> # Remove specified image from this machine
docker image rm $(docker image ls -a -q) # Remove all images from this machine
docker login # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag # Tag <image> for upload to registry
docker push username/repository:tag # Upload tagged image to registry
docker run username/repository:tag # Run image from a registry