Docker
Docker简介
简介:
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版)
Docker的应用场景
- 在服务型环境中部署和调整数据库或其他的后台应用。
- Web 应用的自动化打包和发布。
- 自动化测试和持续集成、发布。
- 快速搭建漏洞环境,方便快速复现漏洞(vulhub)
Docker架构与相关概念
Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker安装
kali安装Docker
-
更新 apt 包索引。
sudo apt-get update
-
安装 apt 依赖包
sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common
-
安装Docker
apt install docker.io
查看Docker安装情况
┌──(root💀kali)-[/home/kali]
└─# dockerUsage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Options:
--config string Location of client config files (default "/root/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker
context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket(s) to connect to
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
Docker使用
Docker容器使用
docker命令查看Commands
Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
常用命令行介绍
docker search
- 用于查找需要的image,该命令会列出可用镜像
┌──(root💀kali)-[/home/kali]
└─# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11120 [OK]
mariadb MariaDB Server is a high performing open sou… 4216 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 825 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 88
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 88
centurylink/mysql Image containing mysql. Optimized to be link… 59 [OK]
databack/mysql-backup Back up mysql databases to... anywhere! 44
deitch/mysql-backup REPLACED! Please use http://hub.docker.com/r… 41 [OK]
docker pull
- 拉取image可以指定tag,如果不指定tag默认:latest
docker pull mysql:latest = docker pull mysql
┌──(root💀kali)-[/home/kali]
└─# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
Digest: sha256:52b8406e4c32b8cf0557f1b74517e14c5393aff5cf0384eff62d9e81f4985d4b
Status: Image is up to date for mysql:latest
docker.io/library/mysql:latest
docker run
- 启动容器 docker run -it ubuntu /bin/bash
-i 交互式操作
-t 伪终端
-d 不直接进入容器
/bin/bash 交互式命令行
docker attach/exec
进入容器
┌──(root💀kali)-[/home/kali]
└─# docker attach 03ce5ef11ed5 2 ⨯
root@03ce5ef11ed5:/#
推荐使用docker exec命令,使用此命令进入容器后再退出,不会导致容器停止
exit
退出容器
root@03ce5ef11ed5:/# exit
exit┌──(root💀kali)-[/home/kali]
docker ps -a
显示所有容器
┌──(root💀kali)-[/home/kali]
└─# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
073c72206c36 ubuntu "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago peaceful_wiles
efe8985dc783 portainer/portainer "/portainer" 30 minutes ago Up 30 minutes 0.0.0.0:9000->9000/tcp prtainer-demo
docker stop <容器ID>
停止容器
┌──(root💀kali)-[/home/kali]
└─# docker stop 073c72206c36
073c72206c36
Docker网络使用
Docker的网络模式大概可以分为5种类型。安装完 Docker,宿主机默认会创建三个网络,分别是bridge网络,host网络,none网络
- bridge
- host
- container模式
- none
- 用户自定义模式(bridge、overlay、macvlan)
bridge模式
容器的默认网络模式,。bridge模式为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,使容器之间,容器和docker host之间实现网络隔离。
docker在安装时会创建一个名为docker0的Linux bridge,在不指定--network的情况下,创建的容器都会默认挂到docker0上面
容器与Host网络是可以ping通的
-
通过Iptables实现容器内访问外部网络
┌──(root💀kali)-[/var/lib/docker]
└─# iptables-save | grep 172.17.0.5 1 ⨯
-A POSTROUTING -s 172.17.0.5/32 -d 172.17.0.5/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.5:80
-A DOCKER -d 172.17.0.5/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
none模式
指定方法: --net="none" ,使用此方法创建的容器没有网络(ping不通host主机),用户可以后续自定义实现灵活,自由的网络配置。
host模式
指定方法:--net="host" 使用host模式的容器可以直接使用docker host的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
container复用模式
指定方法: --net="container:name or id" 如下例子可以看出来,两者的网络完全相同。
User-defined模式
用户自定义模式允许用户自己配置网络,满足用户高度定制化的需求
用户自定义模式
网络配置命令行介绍
使用以下命令查看docker network命令行
docker network --help
┌──(root💀kali)-[/var/lib/docker]
└─# docker network --help 130 ⨯Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networksRun 'docker network COMMAND --help' for more information on a command.
-
ls 显示所有docker局域网络
┌──(root💀kali)-[/var/lib/docker]
└─# docker network ls
NETWORK ID NAME DRIVER SCOPE
5f2ed9e21b68 bridge bridge local
71b303a50562 host host local
b0425f1e8130 ls bridge local
c6bd35740aff none null local
-
create 创建一个docker局域网络
┌──(root💀kali)-[/var/lib/docker]
└─# docker network create mytestnet 1 ⨯
f5d1a8dcffe34a880118f9ef9a9293c78934803d58814c3d0addc7d9768dc729
-
connect 将某个容器连接到一个docker网络
1、下载两个镜像,并启动容器
docker pull redis
docker pull nginx
docker run -itd --name redis redis
docker run -d --name nginx -p 80:80 --privileged=true nginx
2、使用docker network connect命令连接网络
docker network connect mytestnet nginx
docker network connect mytestnet redis
3、也可以在创建容器时,使用--network 参数指定网络;使用--network-alias参数指定别名
docker run -itd --name redis --network mytestnet --network-alias redis redis
docker run -d --name nginx --network mytestnet --network-alias nginx -p 80:80 --privileged=true nginx
-
inspect 显示某个局域网络信息
┌──(root💀kali)-[/var/lib/docker]
└─# docker network inspect mytestnet
[
{
"Name": "mytestnet",
"Id": "f5d1a8dcffe34a880118f9ef9a9293c78934803d58814c3d0addc7d9768dc729",
"Created": "2021-07-14T05:06:07.49185851-04:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"689b2e53db1561a8840e563804a68ea2cc00a34b9d6444a8c3fc4e646a87731f": {
"Name": "redis",
"EndpointID": "154688f81b14161c9403124143b22fcc80633608b9eac0e34f19d9e0fab82469",
"MacAddress": "02:42:ac:14:00:03",
"IPv4Address": "172.20.0.3/16",
"IPv6Address": ""
},
"ecd50c6a67df4c84b371458a1698c2ff2c394dd69367d1d69933628c11e4dd3a": {
"Name": "nginx",
"EndpointID": "64f55aa285906a8418e6d36170e5da57a6ceba6adad3bd2fad0a411277f2c31b",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
-
disconnect 将某个容器退出某个局域网络
┌──(root💀kali)-[/var/lib/docker]
└─# docker network disconnect mytestnet nginx
-
rm 删除docker网络(注意一定要先把network内的容器退出网络)
┌──(root💀kali)-[/var/lib/docker]
└─# docker network rm mytestnet
mytestnet
prune 删除所有未引用的docker局域网络
Dockerfile
介绍
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
使用 Dockerfile 定制镜像
mkdir dockertest
cd dockertest
新建Dockerfile,写入以下命令
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
build镜像
docker build -t nginx:v3 .
查看镜像
docker images
常见命令
COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:
COPY <源路径1>... <目标路径>
ADD
ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
- ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
- ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
CMD
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
- CMD 在docker run 时运行。
- RUN 是在 docker build。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
CMD <shell 命令>
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
ENTRYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
ENV
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
- 避免重要的数据,因容器重启而丢失,这是非常致命的。
- 避免容器不断变大。
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
WORKDIR
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:
WORKDIR <工作目录路径>
LABEL
LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
比如我们可以添加镜像的作者:
LABEL org.opencontainers.image.authors="runoob"
Docker Volume
概念
在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:
(1)volumes:Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式)
由上图可以知道,目前所有Container的数据都保存在了这个目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就上面这一堆很长ID的名字)卷。
(2)bind mounts:意为着可以存储在宿主机系统的任意位置;(比较常用的方式)但是,bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。
(3)tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统;(一般都不会用的方式)
相关使用
Volume使用
1、管理卷
# docker volume create edc-nginx-vol // 创建一个自定义容器卷
# docker volume ls // 查看所有容器卷
# docker volume inspect edc-nginx-vol // 查看指定容器卷详情信息
┌──(root💀kali)-[/var/lib/docker/volumes]
└─# docker volume inspect edc-nginx-vol
[
{
"CreatedAt": "2021-08-04T00:35:45-04:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/edc-nginx-vol/_data",
"Name": "edc-nginx-vol",
"Options": {},
"Scope": "local"
}
]
2、创建使用指定卷的容器
有了自定义容器卷,我们可以创建一个使用这个数据卷的容器,这里我们以nginx为例:
docker run -d -it --name=edc-nginx -p 8800:80 -v edc-nginx-vol:/usr/share/nginx/html nginx
3、清理卷
docker stop edc-nginx // 暂停容器实例
docker rm edc-nginx // 移除容器实例
docker volume rm edc-nginx-vol // 删除自定义数据卷
bind mounts
1、使用卷创建一个容器
docker run -d -it --name=edc-nginx2 -v /app/www:/usr/share/nginx/html nginx
2、验证绑定
docker inspect edc-nginx
Docker compose
介绍
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
安装
curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
查看
docker-compose -v
使用
1、准备
mkdir composetest
cd composetest
2、创建app.py,并写入以下内容
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
3、创建requirements.txt,并写入以下内容
flask
redis
4、创建 Dockerfile 文件,并写入以下内容
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
5、创建 docker-compose.yml,并写入以下内容
# yaml 配置
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
6、使用 Compose 命令构建和运行应用
docker-compose up
Docker可视化工具Portainer
介绍
Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。
安装
查找镜像
┌──(root💀kali)-[/home/kali]
└─# docker search portainer
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
portainer/portainer This Repo is now deprecated, use portainer/p… 2101
portainer/portainer-ce Portainer CE - Making Docker and Kubernetes … 600
portainer/agent An agent used to manage all the resources in… 108
portainer/templates App Templates for Portainer http://portainer… 23
lihaixin/portainer docker ui 15 [OK]
下载镜像
┌──(root💀kali)-[/home/kali]
└─# docker pull portainer/portainer
Using default tag: latest
latest: Pulling from portainer/portainer
94cfa856b2b1: Pull complete
49d59ee0881a: Pull complete
a2300fd28637: Pull complete
Digest: sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f
Status: Downloaded newer image for portainer/portainer:latest
docker.io/portainer/portainer:latest
运行
docker run -d -p 9000:9000
--restart=always
-v /var/run/docker.sock:/var/run/docker.sock
--name prtainer-demo
portainer/portainer
运行界面
浏览器输入IP:9000,显示如下
使用
- 可以连接本地Docker
- 可以管理远程主机的Docker
可以在Dashboard显示终端相关信息,如CPU,内存,Images
概念解释
container -> container(容器)
stack -> docker compose(容器编排工具)
Images -> Images(镜像)
Volume -> Volume(卷)
Networks -> Networks(网络)
实战安装
本部分演示单独安装和使用Stacks安装
单独安装Wordpress
- 创建网络
- 安装mysql
- 安装wordpress
Docker stack安装Wordpress
version: '2' #compose文件版本
services:
db: # 服务1:db
image: mysql:5.7 # 使用镜像 mysql:5.7版本
volumes:
- db_data:/var/lib/mysql # 数据持久化
restart: always # 容器服务宕机后总是重启
environment: # 环境配置
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress: # 服务2:wordpress
depends_on: # wordpress服务启动时依赖db服务,所以会自动先启动db服务
- db
image: wordpress:latest # 使用镜像 wordpress:latest最新版
ports:
- "8000:80" #端口映射8000:80
restart: always
environment: # 环境
WORDPRESS_DB_HOST: db:3306 # wordpress连接db的3306端口
WORDPRESS_DB_USER: wordpress # wordpress的数据库用户为wordpress
WORDPRESS_DB_PASSWORD: wordpress # wordpress的数据库密码是wordpress
WORDPRESS_DB_NAME: wordpress # wordpress的数据库名字是wordpress
volumes:
db_data: {}