Docker采用client-server架构,client和daemon间使用REST API进行通信。client和daemon能够运行在相同或不一样的机器。daemon间也能够经过Docker API通信。
Docker Registry存储image,Docker Hub是默认的公有Registry,也可配置使用私有Registry。
使用Docker时会涉及image、container、network、volume、plugin等对象。html
Capabilities | Community Edition | Enterprise Edition Basic | Enterprise Edition Standard | Enterprise Edition Advanced |
---|---|---|---|---|
Container engine and built in orchestration, networking, security | yes | yes | yes | yes |
Certified infrastructure, plugins and ISV containers | yes | yes | yes | |
Image management | yes | yes | ||
Container app management | yes | yes | ||
Image security scanning | yes |
自17年3月,Docker版本号采用YY.mm.patch格式,YY.mm表明年月。node
在CentOS 7或RHEL 7上可直接使用yum安装,以下:python
# yum install docker # systemctl enable docker # systemctl start docker
docker配置文件位置:
/etc/sysconfig/docker
/etc/docker目录linux
安装官方最新版本docker,步骤以下:nginx
如安装过Docker先卸载,旧版本称为docker或docker-engine,:redis
# 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
# yum update
安装最新版的container-selinuxshell
# 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时可能会显示以下错误:apache
Error: Package: docker-ce-18.06.0.ce-3.el7.x86_64 (docker-ce-edge) Requires: container-selinux >= 2.9
yum-utils提供yum-config-manager工具,用来配置Docker Repository;devicemapper storage driver须要device-mapper-persistent-data和lvm2json
# yum install -y yum-utils device-mapper-persistent-data lvm2
# 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
# yum install docker-ce # systemctl enable docker # systemctl start 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
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
执行以上命令后需从新登陆或重启。
# yum remove docker-ce
Images、 containers、 volumes、customized configuration files不会自动删除,执行如下命令删除:
# rm -rf /var/lib/docker
CLI | Description |
---|---|
Engine CLI | The main CLI for Docker, includes all docker and dockerd commands |
Compose CLI | The CLI for Docker Compose, which allows you to build and run multi-container applications |
Machine CLI | Manages virtual machines that are pre-configured to run Docker |
DTR CLI | Deploy and manage Docker Trusted Registry |
UCP CLI | Deploy 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 [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
运行以上命令后,会执行如下操做:
容器启动后,能够执行shell命令,以下:
root@f7cbdac22a02:/# hostname root@f7cbdac22a02:/# cat /etc/hosts root@f7cbdac22a02:/# yum install -y vim
root@f7cbdac22a02:/# exit
Detached模式
当指定-d选项后,启用Detached模式,container将在后台运行。
$ docker run -d -p 80:80 my_image nginx -g 'daemon off;'
Container identification
有三种类型:
Identifier type | Example 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能够从container建立image。
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Options
Name, shorthand | Default | Description |
---|---|---|
--author , -a | Author (e.g., “John Hannibal Smith hannibal@a-team.com”) | |
--change , -c | Apply Dockerfile instruction to the created image | |
--message , -m | Commit message | |
--pause , -p | true | Pause 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
从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 .
Command | Description |
---|---|
docker attach | Attach local standard input, output, and error streams to a running container |
docker container | Manage containers |
docker cp | Copy files/folders between a container and the local filesystem |
docker create | Create a new container |
docker diff | Inspect changes to files or directories on a container’s filesystem |
docker exec | Run a command in a running container |
docker export | Export a container’s filesystem as a tar archive |
docker kill | Kill one or more running containers |
docker logs | Fetch the logs of a container |
docker pause | Pause all processes within one or more containers |
docker port | List port mappings or a specific mapping for the container |
docker ps | List containers |
docker rename | Rename a container |
docker restart | Restart one or more containers |
docker rm | Remove one or more containers |
docker run | Run a command in a new container |
docker start | Start one or more stopped containers |
docker stats | Display a live stream of container(s) resource usage statistics |
docker stop | Stop one or more running containers |
docker top | Display the running processes of a container |
docker unpause | Unpause all processes within one or more containers |
docker update | Update configuration of one or more containers |
docker wait | Block 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
Command | Description |
---|---|
docker build | Build an image from a Dockerfile |
docker commit | Create a new image from a container’s changes |
docker history | Show the history of an image |
docker image | Manage images |
docker images | List images |
docker import | Import the contents from a tarball to create a filesystem image |
docker load | Load an image from a tar archive or STDIN |
docker manifest | Manage Docker image manifests and manifest lists |
docker pull | Pull an image or a repository from a registry |
docker push | Push an image or a repository to a registry |
docker rmi | Remove one or more images |
docker save | Save one or more images to a tar archive (streamed to STDOUT by default) |
docker search | Search the Docker Hub for images |
docker tag | Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE |
docker trust | Manage 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`
Command | Description |
---|---|
docker login | Log in to a Docker registry |
docker logout | Log out from a Docker registry |
docker pull | Pull an image or a repository from a registry |
docker push | Push an image or a repository to a 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以使配置生效。
# 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
为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'
$ docker run localhost:5000/hello-world
列出全部image:
curl http://localhost:5000/v2/_catalog
列出hello-world image:
curl http://localhost:5000/v2/hello-world/tags/list
经过上面方式建立的registry其协议为http,是不安全的,只适用于本地使用,若要从外部访问registry,须要编辑/etc/docker/daemon.json,增长insecure-registries,以下:
{ "insecure-registries": ["192.168.122.1:5000"] }
配置完毕后需重启docker。
以自签名证书为例,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
$ docker stop registry $ docker rm 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
$ 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获取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中。
除默认Registry外,使用docker时必须指定Registry域名,可否像Maven同样统一使用一个仓库呢?Nexus 3支持Docker Repository,同Maven同样分为三种类型:group、hosted、proxy。hosted至关于私有Registry,用来存储公司内部image;proxy为代理Registry;group能够将hosted、proxy、group三者组合在一块儿。
下面建立docker.io的代理,依次点击Repository -> Repositories -> Create repository -> docker(proxy) :
参数说明:
Repository Connectors Docker Client链接Repository的地址,仅需指定HTTP或HTTPS端口,若使用HTTPS则启动Nexus时也需使用HTTPS。通常不直接访问Proxy,而是经过group,此处没必要配置。
Force basic authentication 若启用则禁止匿名访问,需提供nexus帐号
Enable Docker V1 API 通常没必要启用V1 API,如今经常使用的是V2 API
Remote Repository:https://registry-1.docker.io ,Docker Index:Use Docker Hub
依次点击Repository -> Repositories -> Create repository -> docker(hosted) :
依次点击Repository -> Repositories -> Create repository -> docker(group) :
首先确认是否启用了匿名访问,依次点击Security -> Anonymous:
其余配置保持默认值。
而后建立docker匿名用户角色并授予适当权限,依次点击Security -> Roles -> Create role - Nexus role:
接下来将角色授予匿名用户,依次点击Security -> Users -> anonymous:
一样,修改/etc/docker/daemon.json:
{ "registry-mirrors": ["https://nexus.itrunner.org:8443"] }
重启docker后测试:
$ docker pull hello-world
从浏览器能够方便的查看已下载的image:
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实战