72.Docker的初级使用:容器 - Go语言中文社区

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的博客)或者为这篇文章点赞,谢谢!

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/a464057216/article/details/71122956
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 21:27:32
  • 阅读 ( 1622 )
  • 分类:docker

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢