文章目录
Kubernetes学习系列文章: Kubernetes-博客专栏
今天在学习极客时间专栏:《深入剖析Kubernetes》,强烈推荐此专栏,讲得很好。
今天在学习专栏的07 | 白话容器基础(三):深入理解容器镜像
到08 | 白话容器基础(四):重新认识Docker容器
,主要介绍了Docker的文件系统以及各个命令。于是我打算写一篇文章做个总结。
Docker的安装
Docker和Docker-compose的安装参考这篇文章:ubuntu/debian安装最新版docker和docker-compose
Docker的使用:docker run命令
容器的运行命令是docker run
-> % docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
查看本地存在的镜像:docker images命令
使用命令docker images
可以查看本地存在的docker镜像。
-> % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest af025d9b3fc0 5 weeks ago 1.38MB
nginx latest f5d7507a17dd 9 months ago 112MB
ubuntu latest 21e0cf71370f 10 months ago 79.9MB
ubuntu 16.04 ee5e81436e6e 10 months ago 108MB
hello-world latest de6f0c40d4e5 11 months ago 4.75kB
编写Dockerfile,制作容器镜像
示例是用Python实现一个web服务器,编写app.py
:
ubuntu@ubuntu [14:06:01] [~/docker-test]
-> % cat app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "hello world from docker!"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
requirements.txt
:
ubuntu@ubuntu [14:05:15] [~/docker-test]
-> % cat requirements.txt
Flask
Dockerfile
:
-> % cat Dockerfile
# 使用官方提供的Python开发镜像作为基础镜像
FROM python:2.7-slim
# 将工作目录切换为/app
WORKDIR /app
# 将当前目录下的所有内容复制到/app下
ADD . /app
# 使用pip命令安装这个应用所需要的依赖
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 允许外界访问容器的80端口
EXPOSE 80
# 设置容器进程为:python app.py,即:这个Python应用的启动命令
CMD ["python", "app.py"]
docker build制作镜像
制作镜像:
ubuntu@ubuntu [14:11:03] [~/docker-test]
-> % ls
Dockerfile app.py requirements.txt
ubuntu@ubuntu [14:11:03] [~/docker-test]
-> % docker build -t docker-test . #最后的点说明Dockerfile在当前目录下
Sending build context to Docker daemon 4.096kB
Step 1/6 : FROM python:2.7-slim
2.7-slim: Pulling from library/python
a4f3dd4087f9: Pull complete
e06ddc179ed3: Pull complete
206a3e884852: Pull complete
e2e23efface3: Pull complete
Digest: sha256:dbbceeffb1e1a7c0761916ffce8ef8a2d96af3e43bb7e2a9839a85d236b9f6ea
Status: Downloaded newer image for python:2.7-slim
---> ddc73531bd33
Step 2/6 : WORKDIR /app
---> Running in 2eca88eec682
Removing intermediate container 2eca88eec682
---> c4c62d4ccc5d
Step 3/6 : ADD . /app
---> d1337db476be
Step 4/6 : RUN pip install --trusted-host pypi.python.org -r requirements.txt
---> Running in b2cd84d42125
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting Flask
Downloading https://files.pythonhosted.org/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz
Building wheels for collected packages: MarkupSafe
Building wheel for MarkupSafe (setup.py): started
Building wheel for MarkupSafe (setup.py): finished with status 'done'
Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-cp27-none-any.whl size=12631 sha256=28bf60bf3b6b3353011b2cc50ba1dba705050b2ef119d1392c02716c4fac0c42
Stored in directory: /root/.cache/pip/wheels/f2/aa/04/0edf07a1b8a5f5f1aed7580fffb69ce8972edc16a505916a77
Successfully built MarkupSafe
Installing collected packages: MarkupSafe, Jinja2, itsdangerous, click, Werkzeug, Flask
Successfully installed Flask-1.1.1 Jinja2-2.10.3 MarkupSafe-1.1.1 Werkzeug-0.16.0 click-7.0 itsdangerous-1.1.0
Removing intermediate container b2cd84d42125
---> 297cbf6d2106
Step 5/6 : EXPOSE 80
---> Running in 1f7616acef2c
Removing intermediate container 1f7616acef2c
---> 198506463fa0
Step 6/6 : CMD ["python", "app.py"]
---> Running in f51cb3e567ef
Removing intermediate container f51cb3e567ef
---> 5ed5ccc82aa2
Successfully built 5ed5ccc82aa2
Successfully tagged docker-test:latest
其中,-t 的作用是给这个镜像加一个 Tag,即:起一个好听的名字。docker build 会自动加载当前目录下的 Dockerfile 文件,然后按照顺序,执行文件中的原语。而这个过程,实际上可以等同于 Docker 使用基础镜像启动了一个容器,然后在容器中依次执行 Dockerfile 中的原语。
需要注意的是,Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层。即使原语本身并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的。
从构建过程中,我们可以看出每一步都会新建一层,即使没有对文件系统进行修改。
查看镜像并运行
-> % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-test latest 5ed5ccc82aa2 6 minutes ago 144MB
-> % docker run -p 2333:80 docker-test
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
-p 2333:80 告诉了 Docker,请把容器内的 80 端口映射在宿主机的 2333端口上。
-> # curl 127.0.0.1:2333
hello world from docker!
查看容器运行状态:docker ps命令
-> # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
006b4b54616c docker-test "python app.py" 4 minutes ago Up 4 minutes 0.0.0.0:2333->80/tcp practical_tereshkova
上传自己编写的docker镜像:docker tag,docker push
先要注册自己的账号:Docker Hub
然后在服务器上登录:
-> # docker login --username username
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
使用docker tag
给镜像完整名字:
-> # docker tag docker-test zhang0peter/docker-test:v1
其中,zhang0peter 是我在 Docker Hub 上的用户名,它的“学名”叫镜像仓库(Repository);“/”后面的 docker-test是这个镜像的名字,而“v1”则是我给这个镜像分配的版本号。
然后docker push
镜像:
-> # docker push zhang0peter/docker-test:v1
The push refers to repository [docker.io/zhang0peter/docker-test]
608dcae90c29: Pushed
b3fb689583a3: Pushed
893425fea372: Pushed
7bf9a2a446ee: Mounted from library/python
06c877367cf2: Mounted from library/python
ce991fa93182: Mounted from library/python
397776efcff9: Mounted from library/python
v1: digest: sha256:eedcc8f8b0fdf2f57f657a425d79390c8d3855ae5a3b9d0bbdde66dcfaca31af size: 1788
现在这个镜像就在公共的Docker Hub
上了:zhang0peter/docker-test - Docker Hub
可以手动拉镜像下来:
docker pull zhang0peter/docker-test
进入容器:docker exec命令
ubuntu@ubuntu [14:59:38] [~]
-> % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
006b4b54616c docker-test "python app.py" 33 minutes ago Up 33 minutes 0.0.0.0:2333->80/tcp practical_tereshkova
ubuntu@ubuntu [15:00:09] [~]
-> % docker exec -it 006b4b54616c /bin/sh
#
docker exec
命令的原理是:
一个进程,可以选择加入到某个进程已有的 Namespace 当中,从而达到“进入”这个进程所在容器的目的,这正是 docker exec 的实现原理。