Docker学习笔记--CLI和Registry

Docker概览

Docker架构

Docker学习笔记--CLI和Registry
Docker采用client-server架构,client和daemon间使用REST API进行通讯。client和daemon可以运行在相同或不同的机器。daemon间也可以通过Docker API通讯。
Docker学习笔记--CLI和Registry
Docker Registry存储image,Docker Hub是默认的公有Registry,也可配置使用私有Registry。
使用Docker时会涉及image、container、network、volume、plugin等对象。

  • Image是用来创建Container的只读模板。一个Image可以建立在另一个Image之上,使用Dockerfile文件配置image。Dockerfile的每一指令创建一个image layer,当更改Dockerfile重建image时,仅更改的layer被重建。
  • Container是Image的运行实例。

Docker版本

  • Community Edition (CE)
  • Enterprise Edition (EE)
CapabilitiesCommunity EditionEnterprise Edition BasicEnterprise Edition StandardEnterprise Edition Advanced
Container engine and built in orchestration, networking, securityyesyesyesyes
Certified infrastructure, plugins and ISV containersyesyesyes
Image managementyesyes
Container app managementyesyes
Image security scanningyes

自17年3月,Docker版本号采用YY.mm.patch格式,YY.mm代表年月。

安装和卸载

在CentOS 7或RHEL 7上可直接使用yum安装,如下:

# yum install docker
# systemctl enable docker
# systemctl start docker

docker配置文件位置:
/etc/sysconfig/docker
/etc/docker目录

安装官方最新版本docker,步骤如下:

卸载旧版本

如安装过Docker先卸载,旧版本称为docker或docker-engine,:

# yum remove docker docker-client docker-client-latest docker-common \
           docker-latest docker-latest-logrotate docker-logrotate \
           docker-selinux docker-engine-selinux docker-engine

目录/var/lib/docker/下的内容不会删除,其中包含images、containers、volumes、networks等。

安装Docker CE

  1. 更新系统
# yum update

安装最新版的container-selinux

# yum install -y http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.66-1.el7.noarch.rpm

如未更新container-selinux,在安装Docker CE时可能会显示如下错误:

Error: Package: docker-ce-18.06.0.ce-3.el7.x86_64 (docker-ce-edge)
           Requires: container-selinux >= 2.9
  1. 安装必须的Package

yum-utils提供yum-config-manager工具,用来配置Docker Repository;devicemapper storage driver需要device-mapper-persistent-data和lvm2

# yum install -y yum-utils device-mapper-persistent-data lvm2
  1. 配置Docker Repository
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

默认stable repository是启用的,若要启用edge或test repository(stable repository是必须的),执行如下命令:

# yum-config-manager --enable docker-ce-edge
# yum-config-manager --enable docker-ce-test
  1. 安装Docker CE
# yum install docker-ce
# systemctl enable docker
# systemctl start docker
  1. 验证docker安装
# docker info
# docker --version
# docker version

运行hello-world:

# docker run hello-world

成功后输出如下:

Unable to find image 'hello-world:latest' locally
Trying to pull repository docker.io/library/hello-world ...
latest: Pulling from docker.io/library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for docker.io/hello-world:latest

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.
    (amd64)
 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.

查看image和container:

# docker images
# docker ps
  1. 用户管理

Docker Daemon绑定了Unix socket,而不是TCP端口,默认Unix socket由root和sudo权限的用户拥有。为了运行docker命令时不使用sudo,创建Unix group "docker"(Docker安装后创建了docker group),将用户添加到docker group即可。当docker daemon启动时,让docker group有读/写Unix Socket权限。

# groupadd docker
# usermod -aG docker $USER

执行以上命令后需重新登录或重启。

卸载Docker CE

# yum remove docker-ce

Images、 containers、 volumes、customized configuration files不会自动删除,执行以下命令删除:

# rm -rf /var/lib/docker

Docker CLI

CLIDescription
Engine CLIThe main CLI for Docker, includes all docker and dockerd commands
Compose CLIThe CLI for Docker Compose, which allows you to build and run multi-container applications
Machine CLIManages virtual machines that are pre-configured to run Docker
DTR CLIDeploy and manage Docker Trusted Registry
UCP CLIDeploy and manage Universal Control Plane

Docke支持多方面的CLI,下面仅涉及Engine CLI docker。

运行不带任何参数的docker命令或docker help,可列出所有可用的docker命令

为了查看某一命令的帮助,执行如下命令:

$ docker run --help

option参数可以组合在一起:

docker run -i -t --name test busybox sh

可以写成:

docker run -it --name test busybox sh

docker run

$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

启动docker container有两种模式:Detached、Foreground,默认是Foreground模式。
Foreground模式
Options:

-a=[]         : Attach to `STDIN`, `STDOUT` and/or `STDERR`
-t              : Allocate a pseudo-tty
--sig-proxy=true: Proxy all received signals to the process (non-TTY mode only)
-i              : Keep STDIN open even if not attached

-i -t组合在一起使用,可以与容器进行交互:

$ docker run -a stdin -a stdout -i -t ubuntu /bin/bash

运行以上命令后,会执行以下操作:

  1. 如本地没有ubuntu image,将从registry获取,相当于手动执行docker pull ubuntu
  2. Docker创建新的容器,相当于运行docker container create
  3. Docker给容器分配可读写的文件系统
  4. Docker创建网络接口连接容器到默认网络
  5. Docker启动容器并执行/bin/bash

容器启动后,可以执行shell命令,如下:

root@f7cbdac22a02:/# hostname
root@f7cbdac22a02:/# cat /etc/hosts
root@f7cbdac22a02:/# yum install -y vim
  1. 输入exit,终止/bin/bash,容器停止但不会被删除,可以重新启动。
root@f7cbdac22a02:/# exit

Detached模式
当指定-d选项后,启用Detached模式,container将在后台运行。

$ docker run -d -p 80:80 my_image nginx -g 'daemon off;'

Container identification
有三种类型:

Identifier typeExample value
UUID long identifier“f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778”
UUID short identifier“f78375b1c487”
Name“evil_ptolemy”

当运行container时,如未使用--name指定容器名,daemon将生成一随机字符串作为名字。

Attach to and detach from a running container

$ docker run -d --name topdemo ubuntu /usr/bin/top -b
$ docker attach topdemo

docker commit

使用docker commit可以从container创建image。

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

Options

Name, shorthandDefaultDescription
--author , -aAuthor (e.g., “John Hannibal Smith hannibal@a-team.com”)
--change , -cApply Dockerfile instruction to the created image
--message , -mCommit message
--pause , -ptruePause container during commit

先创建一个Container

$ docker run -t -i training/sinatra /bin/bash

然后运行shell脚本更新container

$ root@0b2616b0e5a8:/# yum install vim

更新完毕后,运行exit退出。
最后使用docker commit创建image:

$ docker commit -m "Added json gem" -a "Kate Smith" 0b2616b0e5a8 ouruser/sinatra:v2

还可以使用--change修改后再创建image:

$ docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" c3f279d17e0a  svendowideit/testimage:version4

docker build

从Dockerfile创建image,这是最常用的方式。

docker build [OPTIONS] PATH | URL | -

下面演示从Dockerfile创建image:
Dockerfile
创建一个空目录,在其内创建名为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
ADD . /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"]

Dockerfile引用了文件app.py 和 requirements.txt,下面在相同目录创建这两个文件:
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)

Build

$ docker build -t friendlyhello .

Container相关命令

CommandDescription
docker attachAttach local standard input, output, and error streams to a running container
docker containerManage containers
docker cpCopy files/folders between a container and the local filesystem
docker createCreate a new container
docker diffInspect changes to files or directories on a container’s filesystem
docker execRun a command in a running container
docker exportExport a container’s filesystem as a tar archive
docker killKill one or more running containers
docker logsFetch the logs of a container
docker pausePause all processes within one or more containers
docker portList port mappings or a specific mapping for the container
docker psList containers
docker renameRename a container
docker restartRestart one or more containers
docker rmRemove one or more containers
docker runRun a command in a new container
docker startStart one or more stopped containers
docker statsDisplay a live stream of container(s) resource usage statistics
docker stopStop one or more running containers
docker topDisplay the running processes of a container
docker unpauseUnpause all processes within one or more containers
docker updateUpdate configuration of one or more containers
docker waitBlock until one or more containers stop, then print their exit codes

示例:
List containers

$ docker ps -a

-a 显示所有的container,默认仅显示运行的container

Stop one or more running containers

$ docker stop CONTAINER [CONTAINER...]

Remove one or more containers

$ docker rm CONTAINER [CONTAINER...]

Remove all containers

$ docker rm `docker ps -a -q`

Start one or more stopped containers

$ docker start CONTAINER [CONTAINER...]

Fetch the logs of a container

$ docker logs -f --until=2s my_container

Run a command in a running container

$ docker exec -d my_container touch /tmp/execWorks

Image相关命令

CommandDescription
docker buildBuild an image from a Dockerfile
docker commitCreate a new image from a container’s changes
docker historyShow the history of an image
docker imageManage images
docker imagesList images
docker importImport the contents from a tarball to create a filesystem image
docker loadLoad an image from a tar archive or STDIN
docker manifestManage Docker image manifests and manifest lists
docker pullPull an image or a repository from a registry
docker pushPush an image or a repository to a registry
docker rmiRemove one or more images
docker saveSave one or more images to a tar archive (streamed to STDOUT by default)
docker searchSearch the Docker Hub for images
docker tagCreate a tag TARGET_IMAGE that refers to SOURCE_IMAGE
docker trustManage trust on Docker images

示例:
pull an image

$ docker pull hello-world

Push an image

$ docker push hello-world:latest

List images

$ docker images

Search images

$ docker search centos

Remove one or more images

$ docker rmi IMAGE [IMAGE...]

Remove all images

$ docker rmi `docker images -a -q`

Registry命令

CommandDescription
docker loginLog in to a Docker registry
docker logoutLog out from a Docker registry
docker pullPull an image or a repository from a registry
docker pushPush an image or a repository to a registry

搭建私有Registry

docker常用命令结构:

docker <command> <registry-hostname>:<registry-port>/<namespace>/<image>:<tag>

默认Registry为Docker Hub,默认namespace为/library,以下三个命令效果相同:

# docker pull hello-world
# docker pull docker.io/hello-world
# docker pull docker.io/library/hello-world

使用Docker中国官方镜像registry.docker-cn.com可以享受到更快的下载速度和更强的稳定性,但只包含流行的公有镜像。

# docker pull registry.docker-cn.com/library/hello-world

可以配置Docker守护进程默认使用Docker中国官方镜像,这样无需在每次拉取时指定registry.docker-cn.com,修改文件/etc/docker/daemon.json添加registry-mirrors键值:

{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

保存后重启Docker以使配置生效。

初识Registry

  1. 使用官方registry镜像创建私有Registry
# mkdir /mnt/registry/docker
# docker run -d -p 5000:5000  --restart always -v /mnt/registry:/var/lib/registry --name registry registry

参数说明:
--restart always 容器异常退出或重启docker后自动重启容器
-v /mnt/registry:/var/lib/registry 绑定/mnt/registry到容器/var/lib/registry目录(存放镜像文件的目录)来实现数据持久化

selinux
如系统启用了selinux,要为/mnt/registry设置selinux安全上下文类型,如下:

# semanage fcontext -a -t container_file_t "/mnt/registry(/.*)?"
# restorecon -R -v /mnt/registry
  1. 上传image

为image打标签后上传到仓库:

$ docker tag hello-world localhost:5000/hello-world:latest
$ docker push localhost:5000/hello-world:latest

tag语法:
Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

也可以使用IMAGE ID:

$ docker tag fce289e99eb9 localhost:5000/hello-world:latest

如系统启用了selinux,但未设置安全上下文类型,上传时会一直retry,报如下错误(可运行journalctl -xe查看原因):

SELinux is preventing /bin/registry from add_name access on the directory docker.

*****  Plugin catchall_labels (83.8 confidence) suggests   *******************

If you want to allow registry to have add_name access on the docker directory
Then you need to change the label on docker
Do
# semanage fcontext -a -t FILE_TYPE 'docker'
where FILE_TYPE is one of the following: container_file_t, container_var_lib_t, nfs_t, svirt_home_t, tmpfs_t, virt_home_t.
Then execute:
restorecon -v 'docker'
  1. 从本地registry运行容器
$ docker run localhost:5000/hello-world
  1. 查看registry中的image

列出所有image:

curl http://localhost:5000/v2/_catalog

列出hello-world image:

curl http://localhost:5000/v2/hello-world/tags/list
  1. 外部访问registry

通过上面方式创建的registry其协议为http,是不安全的,只适用于本地使用,若要从外部访问registry,需要编辑/etc/docker/daemon.json,增加insecure-registries,如下:

{
  "insecure-registries": ["192.168.122.1:5000"]
}

配置完毕后需重启docker。

SSL Registry

  1. 获取证书

以自签名证书为例,Registry URL为registry.itrunner.org,生成自签名证书:

$ cd /mnt/registry
$ mkdir certs
$ openssl req -newkey rsa:2048 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt -subj /C=CN/ST=Beijing/L=Beijing/CN=registry.itrunner.org/OU=itrunner/O=itrunner/emailAddress=sjc-925@163.com

同样,如系统启用了selinux,需给certs目录指定安全上下文:

# semanage fcontext -a -t container_file_t "certs(/.*)?"
# restorecon -R -v certs

每台使用这个Registry的主机都需将自签名证书拷贝到/etc/docker/certs.d/registry.itrunner.org目录下:

# mkdir /etc/docker/certs.d/registry.itrunner.org
# cp certs/domain.crt /etc/docker/certs.d/registry.itrunner.org
  1. 删除当前运行的Registry
$ docker stop registry
$ docker rm registry
  1. 配置证书重新运行Registry
$ docker run -d --restart always --name registry -v /mnt/registry:/var/lib/registry \
-v "$(pwd)"/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-p 443:443 \
registry
  1. 测试
$ curl -k https://registry.itrunner.org/v2/
$ docker tag hello-world registry.itrunner.org/hello-world
$ docker push registry.itrunner.org/hello-world
$ docker pull registry.trunner.org/hello-world

Registry Proxy

每次都从远程Registry获取image浪费网络资源,效率低下。虽然我们可以先从远程pull,再push到私有Registry,但这样操作非常烦琐。Registry Proxy可以本地存储image,减少了重复的pull操作。Registry Proxy不支持push。
这次我们使用配置文件运行registry,执行以下命令获取默认配置文件:

$ docker run -it --rm --entrypoint cat registry /etc/docker/registry/config.yml > config.yml

文件内容如下:

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

增加proxy配置:

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: 0.0.0.0:443
  headers:
    X-Content-Type-Options: [nosniff]
  tls:
    certificate: /var/lib/registry/certs/domain.crt
    key: /var/lib/registry/certs/domain.key
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
proxy:
  remoteurl: https://registry-1.docker.io

修改/etc/docker/daemon.json:

{
  "registry-mirrors": ["https://registry.itrunner.org"]
}

重启docker后运行registry:

$ docker run -d --restart always --name registry-proxy -p 443:443 -v /mnt/registry:/var/lib/registry \
registry /var/lib/registry/config.yml

测试:

$ docker pull hello-world

查看proxy:

$ curl -k https://registry.itrunner.org/v2/_catalog
{"repositories":["library/hello-world"]}

可以看到hello-world已保存到proxy中。

搭建Nexus私服

除默认Registry外,使用docker时必须指定Registry域名,能否像Maven一样统一使用一个仓库呢?Nexus 3支持Docker Repository,同Maven一样分为三种类型:group、hosted、proxy。hosted相当于私有Registry,用来存储公司内部image;proxy为代理Registry;group可以将hosted、proxy、group三者组合在一起。

Docker Proxy

下面创建docker.io的代理,依次点击Repository -> Repositories -> Create repository -> docker(proxy) :
Docker学习笔记--CLI和Registry
参数说明:
Repository Connectors Docker Client连接Repository的地址,仅需指定HTTP或HTTPS端口,若使用HTTPS则启动Nexus时也需使用HTTPS。一般不直接访问Proxy,而是通过group,此处不必配置。
Force basic authentication 若启用则禁止匿名访问,需提供nexus账号
Enable Docker V1 API 一般不必启用V1 API,现在常用的是V2 API
Docker学习笔记--CLI和Registry
Remote Repository:https://registry-1.docker.io ,Docker Index:Use Docker Hub
Docker学习笔记--CLI和Registry

Docker Hosted

依次点击Repository -> Repositories -> Create repository -> docker(hosted) :
Docker学习笔记--CLI和Registry

Docker Group

依次点击Repository -> Repositories -> Create repository -> docker(group) :
Docker学习笔记--CLI和Registry

匿名访问

首先确认是否启用了匿名访问,依次点击Security -> Anonymous:
Docker学习笔记--CLI和Registry
其他配置保持默认值。
然后创建docker匿名用户角色并授予适当权限,依次点击Security -> Roles -> Create role - Nexus role:
Docker学习笔记--CLI和Registry
接下来将角色授予匿名用户,依次点击Security -> Users -> anonymous:
Docker学习笔记--CLI和Registry

使用私服

同样,修改/etc/docker/daemon.json:

{
  "registry-mirrors": ["https://nexus.itrunner.org:8443"]
}

重启docker后测试:

$ docker pull hello-world

从浏览器可以方便的查看已下载的image:
Docker学习笔记--CLI和Registry

常见问题

docker error initializing network controller
删除/var/lib/docker/network/files下的文件,重新启动。

参考文档

Docker Documentation
Product Manuals
Docker Glossary
Reference Documentation
Docker Samples
Docker中国
Best practices for writing Dockerfiles
How to Set Up a Registry Proxy Cache with Docker Open Source Registry
Jenkins与Docker的自动化CI/CD实战

转载于:https://blog.51cto.com/7308310/2161552

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值