72.Docker的初级使用:容器

转载请注明原始出处:http://blog.csdn.net/a464057216/article/details/71122956

后续此博客不再更新,欢迎大家搜索关注微信公众号“测开之美”,测试开发工程师技术修炼小站,持续学习持续进步。
在这里插入图片描述

镜像和容器

镜像是可执行的、独立的、轻量包,包含了软件运行需要的一切,比如代码、库、环境变量和配置文件等。镜像没有状态也不会改变。
容器是镜像在内存中的一个运行实例,容器的运行环境与宿主环境完全隔离,只会访问宿主的端口或文件。容器在宿主机的内核上像普通程序一样运行在单独的进程中,没有额外的内存开销,虚拟机中的程序只能通过hypervisor获得宿主资源的虚拟访问权限。容器的性能比虚拟机更好。

通过Docker引擎,用户不必担心自己的电脑是否可以运行Docker镜像中的程序,Docker容器总是可以运行的。
上一篇博文中,通过启动hello-world程序验证Docker是否成功安装时,docker run hello-world中的run是一个创建和运行容器的子命令,hello-world告诉Docker加载哪个镜像到容器中。

使用容器

以Python应用开发为例,通常希望产品机器和开发机器使用相同的Python运行环境,借助Docker可以将可执行的Python运行环境封装在容器中,这样同一个程序无论在哪里都使用同样的Python运行环境。Dockerfile定义容器内的环境发生了什么,访问文件系统、网络接口等都是与宿主机隔离的,所以需要定义将外界的哪些文件拷贝到容器环境中、容器的端口与宿主机端口的映射关系等。

# 使用官方的Python 2.7-slim作为基准镜像
FROM python:2.7-slim

# 创建目录/app并切换当前工作目录到该目录(构建容器时,默认以root身份进行)
WORKDIR /app

# 将Dockerfile所在目录的内容拷贝至/app
ADD . /app

# 使用pip安装requirements.txt中的包
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# 容器开放80端口给外界
EXPOSE 80

# 定义环境变量NAME
ENV NAME World

# 容器启动时通过python app.py启动应用程序
CMD ["python", "app.py"]

以下是requirements.txt中的内容:

Flask
Redis

以下是app.py中的内容:

from flask import Flask                                            
from redis import Redis, RedisError                                
import os                                                          
import socket                                                      
                                                                   
# 连接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', "mars"),             
            hostname=socket.gethostname(), visits=visits)          
                                                                   
if __name__ == "__main__":                                         
    app.run(host='0.0.0.0', port=80)                               

因为Dockerfile中没有安装Redis,所以这个程序访问Redis会报错。第7行初始化redis对象时,host参数给定的redis表示域名。将Dockerfilerequirements.txtapp.py放在同一目录,构建容器。-t参数表示为镜像设置名字及标记,遵循name:tag的格式;如果只提供一个字符串,则赋值给name参数,tag取默认的latest;如果未提供-t参数,则name和tag默认为<none>(注意命令最后的点):

# Written by: CSDN - Mars Loo的博客
$ docker build -t friendlyhello:1 .
Sending build context to Docker daemon 4.608 kB
Step 1/7 : FROM python:2.7-slim
2.7-slim: Pulling from library/python
cd0a524342ef: Pull complete 
34a63ab31b00: Pull complete 
d9acb0d1bdb2: Pull complete 
Digest: sha256:b5ae405a173110610c594035b5cae5e39a6f305b8e94fb116e9b5a5434412f30
Status: Downloaded newer image for python:2.7-slim
 ---> 7fd4e5a52ace
Step 2/7 : WORKDIR /app
 ---> 6e604ee6a4bb
Removing intermediate container 18b4e7ad0534
Step 3/7 : ADD . /app
 ---> a10207cfd577
Removing intermediate container 4a9bdc498ad1
Step 4/7 : RUN pip install -r requirements.txt
 ---> Running in 54e7c89c18d6
Collecting Flask (from -r requirements.txt (line 1))
  Downloading Flask-0.12.1-py2.py3-none-any.whl (82kB)
Collecting Redis (from -r requirements.txt (line 2))
  Downloading redis-2.10.5-py2.py3-none-any.whl (60kB)
Collecting itsdangerous>=0.21 (from Flask->-r requirements.txt (line 1))
  Downloading itsdangerous-0.24.tar.gz (46kB)
Collecting Jinja2>=2.4 (from Flask->-r requirements.txt (line 1))
  Downloading Jinja2-2.9.6-py2.py3-none-any.whl (340kB)
Collecting Werkzeug>=0.7 (from Flask->-r requirements.txt (line 1))
  Downloading Werkzeug-0.12.1-py2.py3-none-any.whl (312kB)
Collecting click>=2.0 (from Flask->-r requirements.txt (line 1))
  Downloading click-6.7-py2.py3-none-any.whl (71kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->Flask->-r requirements.txt (line 1))
  Downloading MarkupSafe-1.0.tar.gz
Building wheels for collected packages: itsdangerous, MarkupSafe
  Running setup.py bdist_wheel for itsdangerous: started
  Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/fc/a8/66/24d655233c757e178d45dea2de22a04c6d92766abfb741129a
  Running setup.py bdist_wheel for MarkupSafe: started
  Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/88/a7/30/e39a54a87bcbe25308fa3ca64e8ddc75d9b3e5afa21ee32d57
Successfully built itsdangerous MarkupSafe
Installing collected packages: itsdangerous, MarkupSafe, Jinja2, Werkzeug, click, Flask, Redis
Successfully installed Flask-0.12.1 Jinja2-2.9.6 MarkupSafe-1.0 Redis-2.10.5 Werkzeug-0.12.1 click-6.7 itsdangerous-0.24
 ---> bfcccbceca04
Removing intermediate container 54e7c89c18d6
Step 5/7 : EXPOSE 80
 ---> Running in 18af59dc08dc
 ---> 2fe58198cdf7
Removing intermediate container 18af59dc08dc
Step 6/7 : ENV NAME World
 ---> Running in 09cc56ac5c82
 ---> 615fcebbb612
Removing intermediate container 09cc56ac5c82
Step 7/7 : CMD python app.py
 ---> Running in 2e338caa34cc
 ---> 7ce17a909fd5
Removing intermediate container 2e338caa34cc
Successfully built 7ce17a909fd5

通过docker images可以查看本地镜像列表:

# Written by: CSDN - Mars Loo的博客
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
friendlyhello       1                   7ce17a909fd5        About a minute ago   194 MB
python              2.7-slim            7fd4e5a52ace        5 days ago           182 MB

启动容器,将宿主机的8400端口映射到容器的80端口:

$ docker run -p 8400:80 friendlyhello:1
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

浏览器访问宿主机的8400端口可以看到容器内获取hostname得到的是容器ID:
这里写图片描述
docker ps可以查看容器ID:

# Written by: CSDN - Mars Loo的博客
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
a4bfc02df983        friendlyhello:1     "python app.py"     22 seconds ago      Up 20 seconds       0.0.0.0:8400->80/tcp   eloquent_stallman

Ctrl+C退出容器应用,使用-d参数后台运行容器,将打印完整的容器ID后退出:

# Written by: CSDN - Mars Loo的博客
$ docker run -dp 8400:80 friendlyhello:1
e25f1119fb394b0271e72ba9da322f72d5e97a35b7189467e75e8ab3f400712a

使用docker stop可以停止该程序:

# Written by: CSDN - Mars Loo的博客
$ docker stop e25f1119fb39        
e25f1119fb39        

如果容器无法被正常停止,可以使用docker kill强制停止:

# Written by: CSDN - Mars Loo的博客
$ docker kill cbf1d0f24414
cbf1d0f24414

如果使用netstat观察宿主机的8400端口,监听的是TCP6即ipv6协议的端口,但其实仍然是可以使用ipv4协议访问的:

# Written by: CSDN - Mars Loo的博客
$ sudo netstat -nlp | grep 8400
tcp6       0      0 :::8400                 :::*                    LISTEN      53408/docker-proxy

共享镜像给他人

共享制作好的镜像给他人,类似共享写好的代码给他人。比如本地commit之后,push到远端的代码托管平台(GitHub或者自建的GitLab平台)。Docker的镜像托管平台称为Docker Registry,默认的Registry是国外的Docker Hub,如果被墙,可以使用国内的https://c.163.com,或者为了产品的安全性自己搭建Docker Registry。
首先需要登录至相应的Docker Registry,docker login命令后的参数表示登录地址,比如:

# Written by: CSDN - Mars Loo的博客
$ docker login hub.c.163.com
Username: marsloo
Password: 
Login Succeeded

为本地镜像打标签,标签相当于建立本地镜像和远程镜像的关联,格式为username/repository:tag,即用户username名下的repository仓库的tag版本。Docker Registry是仓库的集合,仓库是镜像的集合:

$ docker tag friendlyhello:1 hub.c.163.com/learndocker/learndocker:v1

镜像打完标签后,如果使用docker images命令查看,会有两个名字不同但image id相同的镜像。
上传打过标签的镜像到Docker Registry:

$ docker push hub.c.163.com/learndocker/learndocker:v1

上传完成后镜像就是公开的了,先删除本地的镜像:

$ docker rmi hub.c.163.com/learndocker/learndocker:v1
$ docker rmi -f friendlyhello:1
$ sudo rm -rf /var/lib/docker

镜像已经共享到公开的Docker Registry,此时在任何装有Docker的机器上都可以运行该镜像了:

$ docker run -p 8400:80  hub.c.163.com/learndocker/learndocker:v1

如果在构建和运行镜像时没有指定冒号后面的tag名,则系统使用默认的latest

接下来推荐阅读通过服务和集群的方式使用Docker,可以方便进行程序规模的扩展和流量的负载均衡。

如果觉得我的文章对您有帮助,欢迎关注我(CSDN:Mars Loo的博客)或者为这篇文章点赞,谢谢!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值