一、简介

1、简介

Docker是开发人员和系统管理员使用容器开发,部署和运行应用程序的平台。

使用Linux容器部署应用程序称为容器化,容器化逐渐变的流行是因为它有以下几个特点:

  • 灵活性:即使是最复杂的应用也可以容器化

  • 轻量性:容器使用并共享主机内核

  • 互换性:可以即时部署更新和升级

  • 便携性:可以在本地构建,云端部署,任何地方运行

  • 扩展性:可以增加并自动分发容器的副本

  • 堆叠性:可以即时地垂直堆叠(stack)各种服务(services)

2、相关概念

  • 镜像和容器

镜像是一个包含程序运行时所需的所有内容:代码、运行时环境、库、环境变量和配置文件等的可执行包。

通过运行镜像可以启动容器,容器是镜像的运行时实例。

  • 容器和虚拟机

容器在Linux上运行并与其他容器共享主机的内核,它运行一个独立的进程,不占用任何其他可执行的内存,因此它是轻量的。

相反,虚拟机运行一个完整的”客户端”操作系统,通过虚拟机管理程序对主机资源进行虚拟访问。通常情况下,虚拟机所使用的资源比大多数应用程序所需要的更多。

二、安装

1、安装Linux虚拟机

由于我之前安装的虚拟机是RedHat,但官网中并没有RedHat的安装介绍,因此需要先安装CentOS或Ubuntu

此处选择Ubuntu Disco 19.04(操作系统要求是64位的)。

2、安装Docker

  • 设置repository

    • 更新软件源中的所有软件
      sudo apt-get update
    
    • 安装软件包,允许通过HTTPS使用库(repository)
      sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
    
    • 添加Docker官方的GPG key
      curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    

    验证:

      sudo apt-key fingerprint 0EBFCD88
    

    • 设置稳定的库(repository)的地址
       sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    
  • 安装Docker引擎

    • 更新软件源
      sudo apt-get update
    
    • 安装最新版Docker引擎
      sudo apt-get install docker-ce docker-ce-cli containerd.io
    
    • 验证是否安装成功
      sudo docker version
    

      sudo docker run hello-world
    
为了使用方便,直接将用户切换到root执行命令。

三、Docker基本命令

  • docker version
docker version [OPTIONS]

显示Docker的版本信息。

  • docker info
docker info [OPTIONS]

显示Docker的系统信息,包括镜像和容器的运行情况等。

1、镜像相关命令

  • docker pull
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

从镜像仓库中拉取或更新指定的镜像。

  • docker imagesdocker image ls
docker images [OPTIONS] [REPOSITORY[:TAG]]
docker image ls

列出本地镜像列表。

  • docker rmi
docker rmi [OPTIONS] IMAGE [IMAGE...]

删除本地的一个或多个镜像,-f:强制删除。

  • docker tag
docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]

将镜像标记为某个库(REPOSITORY)下。

  • docker build
docker build [OPTIONS] PATH | URL | -

使用Dockerfile文件创建镜像。

  • docker history
docker history [OPTIONS] IMAGE

查看镜像的创建历史。

2、容器相关命令

  • docker container ls
docker container ls 

列出所有容器信息。

  • docker run
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

创建一个新的容器并运行一个命令。

  • docker start
docker start [OPTIONS] CONTAINER [CONTAINER...]

启动一个或多个未启动的容器。

  • docker stop
docker stop [OPTIONS] CONTAINER [CONTAINER...]

停止一个或多运行中的容器。

  • docker restart
docker restart [OPTIONS] CONTAINER [CONTAINER...]

重启容器。

  • docker kill
docker kill [OPTIONS] CONTAINER [CONTAINER...]

杀掉一个运行中的容器。

  • docker rm
docker rm [OPTIONS] CONTAINER [CONTAINER...]

删除一个或多个容器。

  • docker exec
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

在运行的容器中执行命令,-i:即时没有attach也保持输入有效;-t:分配一个伪终端。

  • docker ps
docker ps [OPTIONS]

列出容器信息。

  • docker top
docker top [OPTIONS] CONTAINER [ps OPTIONS]

查看容器中运行的进程信息。

  • docker inspect
docker inspect [OPTIONS] NAME|ID [NAME|ID...]

查看镜像/容器的元数据。

  • docker attach
docker attach [OPTIONS] CONTAINER

将本地标准输入,输出和错误流附加到正在运行的容器上。

  • docker port
docker port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]]

列出容器的端口映射。

  • docker cp
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

此命令用于在主机和容器之前拷贝数据。

四、运行镜像

此处以运行nginx镜像为例,具体如何使用此镜像可参考:NGINX - How to use this image

1、从仓库中拉取镜像

之前运行docker run hello-world时,由于在本地找不到hello-world的镜像,因此自动从仓库中拉取。此处手动拉取nginx镜像:
docker pull nginx

2、运行镜像

以后台方式运行nginx:

docker run -d nginx 

3、在容器中执行命令

查看容器信息:

docker ps

进入容器终端并执行命令:

docker exec -it e58ff9759645 bash
注:e58ff9759645 为容器ID。

4、端口映射

先停止容器:

docker stop e58ff9759645

重新运行,暴露外部端口:

docker run -d -p 8080:80 nginx

访问虚拟机8080端口:

五、制作镜像

1、编写Dockerfile

Dockerfile 定义了容器内部环境发生的事情,在此容器环境中访问网络接口、磁盘驱动器等资源都是虚拟化的,与系统的其他部分是隔离的,因此需要将端口映射到外部;并指定要拷贝到此环境中的文件。这样使用Dockerfile文件构建(build)出的应用程序在任何地方运行都会具有完全相同的行为。

  • 创建目录和文件

创建一个新的目录:

mkdir hello

切换到该目录下,创建Dockerfile文件:

cd hello
mkdir Dockerfile
  • 编辑Dockerfile

在Dockerfile中增加以下内容:

# Use an official Python runtime as a parent image
FROM python:3.6-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"]

2、编写应用程序

  • 创建应用程序文件

创建Dockerfile中使用到的requirements.txtapp.py

touch requirements.txt
touch app.py
  • 编辑文件内容

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)

3、构建

  • 构建命令
docker build --tag=friendlyhello .
或
docker build -t=friendlyhello .
  • 错误及解决方法

如果出现以下错误:

Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) 
after connection broken by ProxyError('Cannot connect to proxy.', NewConnectionError(
'<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at xxxxxxxxxx>: 
Failed to establish a new connection:,))': 

则需要在/etc/docker/目录下创建或编辑daemon.json文件,增加dns的配置:

{
  "dns": ["your_dns_address", "8.8.8.8"]
}

之后重启docker服务:

service docker restart

然后再次构建即可成功。

4、运行及效果

运行镜像,并将容器暴露的80端口映射到主机的8080端口:

docker run -p 8080:80 friendlyhello

运行效果:

由于Redis尚未运行,因此显示出了错误信息。
参考资料