Docker入门:边玩边学
Docker
概念
Docker
是开发人员和系统管理员使用容器开发,部署和运行应用程序的平台。使用Linux
容器部署应用程序称为容器化。容器不是新的,但它们用于轻松部署应用程序。
容器化越来越受欢迎,因为容器是:
- 灵活:即使是最复杂的应用也可以集装箱化。
- 轻量级:容器利用并共享主机内核。
- 可互换:你可以即时部署更新和升级。
- 便携式:你可以在本地构建,部署到云,并在任何地方运行。
- 可扩展:你可以增加并自动分发容器副本。
- 可堆叠:你可以垂直和即时堆叠服务。
Docker Image(图像/镜像)
通过运行Docker Image
(图像/镜像)启动容器。一个图像是一个可执行的包,其中包括运行应用程序所需的所有内容的代码,运行时的库,环境变量,和配置文件。
容器和虚拟机
一个容器中运行原生Linux
和共享主机与其它容器的内核。它运行一个独立的进程,不占用任何其他可执行文件的内存,使其轻量级。
相比之下,虚拟机(VM
)运行一个完整的“客户”操作系统,通过虚拟机管理程序对主机资源进行虚拟访问。通常,VM
提供的环境比大多数应用程序需要的资源更多。
Dockerfile
Dockerfile
主要用来构建图像。它定义了容器内环境中发生的事情。对网络接口和磁盘驱动器等资源的访问在此环境中进行虚拟化,该环境与系统的其他部分隔离。
一般的,Dockerfile
分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
安装和检查
在Ubuntu 16.04
系统上面使用如下命令安装并且把当前用户加入docker
用户组,这样就不需要每次运行docker
命令都输入sudo
:
$ sudo apt-get install docker.io
$ sudo usermod -aG docker $USER
重新退出和登录当前用户后,接下来可以使用如下命令简单的检查docker
正常运作:
## Display Docker version and info
docker version
docker info
## Execute Docker image
docker run hello-world
## List Docker images
docker images
## List Docker containers (running, all, all in quiet mode)
docker ps
docker ps -a
docker ps -aq
从Dockerfile
开始
在本地计算机上创建一个空目录。进入新目录(cd
),创建一个名为的文件Dockerfile
,将以下内容复制并粘贴到该文件中,然后保存。
# Use an official Python runtime as a parent image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -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"]
再创建两个文件:requirements.txt
和 app.py
,将它们放在Dockerfile
同一个文件夹中。这完成了我们的应用程序,可以看到它非常简单。上述Dockerfile
被内置到图像,app.py
和requirements.txt
是因为Dockerfile
的COPY
命令而存在,得益于EXPOSE
命令,我们可以通过HTTP访问该端口。
requirements.txt
Flask
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)
现在我们看到pip install -r requirements.txt
为Python
安装Flask
和Redis
库,应用程序打印环境变量NAME
,以及socket.gethostname()
的输出。最后,因为Redis
没有运行(因为我们只安装了Python
库,而不是Redis
本身),我们应该期望在这里看到尝试失败并产生错误消息。
构建应用程序
我们准备构建应用程序。确保你仍处于新目录的顶层。这是ls
应该显示的内容:
$ ls
Dockerfile app.py requirements.txt
现在运行build
命令。这将创建一个Docker
镜像,我们将使用该–tag选项命名(或者-t)
docker build --tag=friendlyhello .
构建好的图像在机器的本地Docker镜像注册表中:
$ docker images
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
运行应用程序:
运行应用程序,使用以下方法将计算机的端口4000映射到容器的已发布端口80:
docker run -p 4000:80 friendlyhello
这时可以在Web浏览器中转到该URL http://localhost:4000
以查看在网页上提供的显示内容。
现在让我们在后台以分离模式运行应用程序:
docker run -d -p 4000:80 friendlyhello
这里获得应用程序的容器ID,然后被踢回终端。容器正在后台运行,通过如下命令可以查看:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
最后可以使用如下命令来结束这个过程:
docker stop 1fa4ab2cf395
删除图像和容器
使用如下命令可以删除图像和容器:
docker rm <hash> # Remove specified container from this machine
docker rm $(docker ps -a -q) # Remove all containers
docker rmi <image id> # Remove specified image from this machine
docker rmi $(docker images -a -q) # Remove all images from this machine
Dockerfile
常用指令
Dockerfile
里面最重要的就是指令部分,指令的一般格式为 INSTRUCTION arguments
,指令包括 FROM 、 MAINTAINER 、 RUN
等。下面是一些常用指令的简单介绍:
FROM
格式为 FROM <image>
或 FROM <image>:<tag>
。
第一条指令必须为 FROM
指令。并且,如果在同一个Dockerfile
中创建多个镜像时,可以使用多个 FROM
指令(每个镜像一次)
RUN
格式为 RUN <command>
或 RUN [“executable”, “param1”, “param2”]
。
前者将在 shell
终端中运行命令,即 /bin/sh -c
;后者则使用 exec
执行。指定使用其它终端可以通过第二种方式实现,例如 RUN [“/bin/bash”, “-c”, “echo hello”]
。
CMD
支持三种格式
-
CMD [“executable”,”param1″,”param2″]
使用exec
执行; -
CMD command param1 param2
在/bin/sh
中执行; -
CMD [“param1″,”param2”]
提供给ENTRYPOINT
的默认参数;
指定启动容器时执行的命令,每个 Dockerfile
只能有一条 CMD
命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD
指定的命令。
EXPOSE
告诉 Docker
服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过-P
,Docker
主机会自动分配一个端口转发到指定的端口。
ENV
格式为 ENV <key> <value>
。 指定一个环境变量,可以被后续 RUN
指令使用,并在容器运行时保持。
ADD
格式为 ADD <src> <dest>
。
该命令将复制指定的 <src>
到容器中的 <dest>
。 其中 <src>
可以是Dockerfile
所在目录的一个相对路径;也可以是一个URL
,还可以是一个 tar
文件(自动解压为目录)。
COPY
格式为 COPY <src> <dest>
。
复制本地主机的 <src>
(为 Dockerfile
所在目录的相对路径)到容器中的 <dest>
。
ENTRYPOINT
两种格式:
ENTRYPOINT [“executable”, “param1”, “param2”]
ENTRYPOINT command param1 param2
配置容器启动后执行的命令,并且不可被 docker run
提供的参数覆盖。每个 Dockerfile
中只能有一个 ENTRYPOINT
,当指定多个时,只有最后一个起效。
VOLUME
格式为 VOLUME [“/data”]
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
WORKDIR
格式为 WORKDIR /path/to/workdir
为后续的 RUN 、 CMD 、 ENTRYPOINT
指令配置工作目录。
ONBUILD
格式为 ONBUILD [INSTRUCTION]
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
上一篇: 如何用U盘给电脑加密图文教程