跳到主要内容

Docker-cheetsheet

最近在实习的过程中,需要将现有的服务上云,使用到了容器化的操作。需要自己制作Dockerfile文件,完成部署。鉴于对于docker技术的不熟练,用了几天时间好好把这个知识梳理了一下。

安装和基础命令详见上一篇文章 Docker安装及基础命令

docker 镜像

拉取镜像

$ docker pull alpine
$ docker pull registry.hub.docker.com/alpine:latest

指定默认的仓库和版本号

[root@VM_118_62_centos ~]# docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
e6b0cf9c0882: Pull complete
Digest: sha256:2171658620155679240babee0a7714f6509fae66898db422ad803b951257db78
Status: Downloaded newer image for alpine:latest

列出镜像

docker images
docker image ls

给镜像加tag

docker tag alpine test 起到了链接的作用

查看镜像

docker inspect IMAGE # 返回json 格式
docker inspect -f {{ ."DockerVersion"}} IMAGE # 以GO 模范返回格式化的信息

搜索镜像

docker search IMAGE # 搜索镜像
docker search --filter=starts=4 IMAGE # 返回收藏超过4的镜像
docker search --filter=is-official=true IMAGE # 返回官方镜像

移除镜像

docker rmi IMAGE # 删除镜像
docker image rm IMAGE # 删除镜像
docker image rm ubuntu:latest # 删除指定tag 的镜像
-f --force # 强制删除

docker image prune
-a, --all Remove all unused images, not just dangling ones (临时镜像)
--filter filter Provide filter values (e.g. 'until=<timestamp>')
-f, --force Do not prompt for confirmation

创建镜像

创建镜像的三种方式:commit、import、build 三个子命令

1.commit 基于现有容器创建

docker run -it alpine /bash/sh

# add a new file to this container 
[root@VM_118_62_centos ~]# docker run -it alpine /bin/sh
/ # touch text
/ # exit

docker [container] commit -m "add a new file" -a "johnjhwang" CONTAINER

注:方括号中的 container 是可以省略不写的。这里指出是说明commit 这个命令是 容器相关的命令 比较建议写全,比如rm 在image 和 container 中都有,避免歧义

-m: 表示 Comment -a: 表示 Author

由于是添加了一个文件,所以镜像的 IAMGE ID 发生了变化

当我们查看新的镜像的时候,能看到我们后续追加的信息。

[root@VM_118_62_centos ~]# docker inspect 764a657de081
[
{
"Id": "sha256:764a657de08117c11b3af9720efe2310386fa99074802ad13f68973081972819",
"Parent": "sha256:cc0abc535e36a7ede71978ba2bbd8159b8a5420b91f2fbc520cdf5f673640a34",
"Comment": "add a new file ",
......
"Author": "johnjhwang",
......
}
]

2.build 基于Dockerfile创建

首先,创建一个文件Dockerfile

文件名默认伟是Dockerfile,或-f 指定自定义名称的dockerfile

# Dockerfile
FROM ubuntu:latest
LABEL version='1.0' maintainer='johnjhwang@tencent.com'
RUN apt-get update &&\
apt-get install -y python3 \
apt-get clean
docker [image] build -t python:3 .(小数点:这是上下文环境为当前目录)

python 是镜像名,3是版本号,如 test1:v1nginx:v2 等,注意,最后有一个点,代表的是上下文环境(当前目录) 。

3. import 基于本地模板导入

// TO DO

存出和载入镜像

docker [image] save -o ubuntu_18.04.tar ubuntu:18.04 # 本地会出现ubuntu_18.04.tar 文件
docker [image] load -i ubuntu_18.04.tar # 导入本地的文件,之后查看镜像库,发现出现了该镜像

这里我们可以用更加简便的写法

docker save alpine > alpine.tar
docker load alpine < alpine.tar

上传镜像 push

1. 登录Docker Hub 账号

docker login artifactory.xxx.works

2.镜像加上tag

docker [image] tag monitor-kit:v0.1 artifactory.xxx.works/docker-xxx/cla/labelling-platform/monitor-kit:v0.2

3.镜像push

docker push artifactory.xxx.works/docker-xxx/cla/labelling-platform/monitor-kit:v0.2

docker 容器

新建容器&&启动容器

create、start、run

docker create/start

docker [container] create -it alpine # 用create创建的容器处于停止状态 Created ,加-it 使用的是默认的sh
docker [container] start CONTAINER # 运行后的容器状态转为 Up

查看状态

[root@VM_118_62_centos ~/desktop]# docker start 77a32260848
[root@VM_118_62_centos ~/desktop]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
77a32260848e alpine "/bin/sh" 2 minutes ago Up 5 seconds naughty_lamport

还有一个更加方便的启动方式,等价于 先执行create 后执行 start

docker run

docker [container] run -it alpine /bin/sh
-t, --tty Allocate a pseudo-TTY 分配一个伪终端
-i, --interactive Keep STDIN open even if not attached 标准输入保持打开
-d, --detach Run container in background and print container ID

暂停终止容器

暂停/恢复容器

状态变为: Up (Paused)

docker [container] pause/unpause CONTAINER

终止/启动容器

stop、kill、运行结束会使容器状态变为: Exited

docker [container] stop/start CONTAINER
-t, --time int Seconds to wait for stop before killing it (default 10)

docker [container] kill CONTAINER

stop 是主动向容器发送 SIGTERM 信号,等待一段时候后,再发送SIGKILL信号来终止容器。 kill 是直接发送SIGKILL信号去终止容器。

有一种情况,当容器运行结束后,状态也会变为Exited

[root@VM_118_62_centos ~]# docker attach test
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
6 root 0:00 ps
/ # exit // 退出后容器会终止

可以看到容器中只有 /bin/sh 命令运行,此时使用 exit 或者 ctrl+d 退出容器,该容器会终止

清除容器

prune

docker container prune  # Remove all stopped containers
-f, --force Do not prompt for confirmation

rm

docker container rm \<CONTAINER ID> # Remove one or more containers
-f, --force Force the removal of a running container (uses SIGKILL)
-l, --link Remove the specified link
-v, --volumes Remove the volumes associated with the container

重启容器

先停止容器后重启容器

docker restart CONTAINER

进入容器

attach

docker attach CONTAINER

exec

exec 相较于 attach 的优势是可以在运行的容器内执行任意命令 Run a command in a running container

docker exec -it  CONTAINER /bin/sh
--detach-keys string Override the key sequence for detaching a container
// 重载退出容器的方法,默认是ctrl+q
-e, --env list Set environment variables
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
-w, --workdir string Working directory inside the container

导入/导出容器

docker [container] export -o test.tar test 
docker [image] import test.tar test01/test02:v1.0

注意: docker export 是 container 下的方法 docker import 是 image 下的方法,不要以为import 后导入到的容器库。

可以看到 docker [image] save 和 dokcer [image] load 是一对,docker [container] export 和 docker [image] import 是一对。但是 load 和 import 同样都是导入到镜像库,区别在什么地方?

  • docker save images_name:将一个镜像导出为文件,再使用docker load命令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比docker export命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。
  • docker export container_id:将一个容器导出为文件,再使用docker import命令将容器导入成为一个新的镜像,但是相比docker save命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。

查看容器

docker [container] inspect CONTAINRER
docker [container] top CONTAINER # 显示docker 内运行的进程
docker [container] stats CONTAINER # 显示docker的状态,CPU,内存,存储,网络等实时监控

* 其他容器命令

制作Dockerfile所需掌握的命令

docker cp 复制文件

Usage:  docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
# FROM 左 TO 右

docker [container] cp data test:/temp

这是将本地路径下的 data 复制到 test 容器的/temp 路径下,注意只是复制文件内容,不没有包含文件夹。

docker [container] cp data test:/temp/data

这样才是把data文件夹移到了目标容器的文件夹下

docker container 命令大全

  attach      Attach local standard input, output, and error streams to a running container
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
exec Run a command in a running container
export Export a container's filesystem as a tar archive
inspect Display detailed information on one or more containers
kill Kill one or more running containers
logs Fetch the logs of a container
ls List containers
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
prune Remove all stopped containers
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
run Run a command in a new container
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
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
wait Block until one or more containers stop, then print their exit codes

docker 容器卷

本章不再详述命令细节,只关注于常用命令

容器中对数据进行持久化的操作,需要借助数据管理操作。

一般有两种管理方式:

  • Data Volumes
  • Data Volume Containers

数据卷(Data Volumes)

创建一个本地数据卷

docker volume create -d local --name haha
-d, --driver string Specify volume driver name (default "local")
--name 重命名

docker volumn create 创建完成的数据卷是在 /var/lib/docker/volumes 下的,可以通过 ls (查看) inspect(详细信息) prune 和 rm 去做进一步的操作。

$ docker volume ls
DRIVER VOLUME NAME
local haha

这里mac需要注意,因为在mac上用docker会在mac上启动一个虚拟机运行docker,因此volume创建的directory并不在你的machine上,而是在虚拟机中。

mac用户如何查看数据卷地址

如何进入mac上的虚拟机的办法请参考:这篇教程

具体的做法是执行:screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

然后查看/var/lib/docker/volumes里面的容器

数据卷的类型

  • volume : 普通数据卷,映射到 /var/lib/docker/volumes下
  • bind: 绑定数据卷,是自己制定的目录
  • tmpfs: 临时数据卷,只存在于内存中,目前没有使用过
docker run -d --name test --mount type=bind,source=/mydata,destination=/opt/mydata CONTAINER COMMAND

这句话是绑定当前目录下的mydata文件夹至docker容器下的/opt/mydata文件夹

还有一个简洁的方式 -v

docker run -d --name test -v /mydata:/opt/mydata CONTAINER COMMAND

数据容器(Data Volume Containers)

创建一个数据卷容器,起别名 dbtest,并挂载 ~/Desktop/dbfile 到当前容器

docker run -it --name dbtest -v ~/Desktop/dbfile:/dbfile alpine:latest

然后,可以在其他容器中使用 --volumes-from 挂载dbtest 中的数据卷

docker run -it --name db1 --volumes-from dbtest alpine
docker run -it --name db2 --volumes-from dbtest alpine

数据卷高级用法:迁移数据

数据的迁移有两步构成:备份+迁移

首先我们使用了上面建立好的 dbtest 数据卷容器,该容器和 ~/Desktop/dbfile 绑定,其中包含了我们需要保存的重要的数据。

备份

docker run --volumes-from dbtest -v $(pwd):/backup --name worker alpine tar cvf /backup/backup.tar /dbfile

这里我们把绑定的本地和容器内的/backup绑定,所以我们用压缩方法,把dbfile 内的数据打包放入了/backup文件夹中,直观的来说,在当前目录下会看到backup.tar 文件。

迁移

先创建一个新的数据卷容器dbtest2

docker run -v ~/Desktop/dbfile2:/dbfile --name dbtest2 alpine

创建新容器,挂载dbtest2的容器,并使用untar解压放在/backup/backup.tar 文件

docker run --volumes-from dbtest2 -v $(pwd):/backup --name worker2 ubuntu tar xvf /backup/backup.tar

docker

端口映射

启动一个web服务

docker run -d -P straining/webapp python app.py  // 随机映射端口,49000~49900到容器内部端口
docker run -d -p 5000:5000 training/webapp python app.py// HostPort:ContainerPort
docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py// IP:HostPort:ContainerPort
docker run -d -p 127.0.0.1::5000 training/webapp python app.py // 自动分配一个端口
docker run -d -p 127.0.0.1::5000/udp training/webapp python app.py // 制定UDP

稍后我们可以看到映射结果(下面是举例)

127.0.0.1:32768->5000/tcp 
0.0.0.0:3306->3306/tcp
127.0.0.1:32768->5000/udp

容器互联

--link name:alias name:连接的容器 alias 容器的别名

容器间的互联是一个比较重要的知识点,后续会写一篇博客完善

实用技巧

alpine 安装telnet、curl 命令

# 镜像加速,将原装的alpine库替换成国内的ustc库
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
# apk库更新
apk update
# 安装ping
apk add curl
# 安装telnet
apk add busybox-extras
# 全部安装
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && apk update && apk add curl && apk add busybox-extras

使用方法

curl http://127.0.0.1:8888/test
telnet 127.0.0.1 8888

参考资料

docker load与docker import