docker容器执行脚本的优雅做法
一般做法
如果我们希望在容器中批量或者定时执行命令,一般的做法是编写好脚本以后把脚本打包到镜像中,或者拷贝容器中,通过CMD或者exec去运行:
$ docker cp [script] [container]:/[path]
$ docker exec [container] [command to run script]
但是这种方式明显不够优雅,首先是必须把脚本搞到容器里面去,其次是没办法大批量或者远程运行。
优雅做法
2.1 单机运行
单机运行时我们可以把脚本直接放宿主机,然后把脚本base64编码后执行,如下:
$ docker exec [container] bash -c "echo $(base64 [script]) | base64 -d | sh"
有人说我不能直接执行吗?或者传明文?答案是不太行,因为你的脚本可能有特殊字符和空行等,直接传脚本会被截断或者解析出问题。
2.2 远程运行
前提条件:
- 开启了docker remote api
步骤:
1. 获取容器列表
GET {http/https}://{host}:{port}/containers/json
响应示例
[
{
"Id": "8dfafdbc3a40",
"Names": [
"/boring_feynman"
],
"Image": "ubuntu:latest",
"ImageID": "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
"Command": "echo 1",
"Created": 1367854155,
"State": "Exited",
"Status": "Exit 0",
"Ports": [
{
"PrivatePort": 2222,
"PublicPort": 3333,
"Type": "tcp"
}
],
"Labels": {
"com.example.vendor": "Acme",
"com.example.license": "GPL",
"com.example.version": "1.0"
},
"SizeRw": 12288,
"SizeRootFs": 0,
"HostConfig": {
"NetworkMode": "default"
},
"NetworkSettings": {
"Networks": {
"bridge": {
"NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID": "2cdc4edb1ded3631c81f57966563e5c8525b81121bb3706a9a9a3ae102711f3f",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
},
"Mounts": [
{
"Name": "fac362...80535",
"Source": "/data",
"Destination": "/data",
"Driver": "local",
"Mode": "ro,Z",
"RW": false,
"Propagation": ""
}
]
},
{
"Id": "9cd87474be90",
"Names": [
"/coolName"
],
"Image": "ubuntu:latest",
"ImageID": "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
"Command": "echo 222222",
"Created": 1367854155,
"State": "Exited",
"Status": "Exit 0",
"Ports": [],
"Labels": {},
"SizeRw": 12288,
"SizeRootFs": 0,
"HostConfig": {
"NetworkMode": "default"
},
"NetworkSettings": {
"Networks": {
"bridge": {
"NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID": "88eaed7b37b38c2a3f0c4bc796494fdf51b270c2d22656412a2ca5d559a64d7a",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.8",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:08"
}
}
},
"Mounts": []
},
{
"Id": "3176a2479c92",
"Names": [
"/sleepy_dog"
],
"Image": "ubuntu:latest",
"ImageID": "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"State": "Exited",
"Status": "Exit 0",
"Ports": [],
"Labels": {},
"SizeRw": 12288,
"SizeRootFs": 0,
"HostConfig": {
"NetworkMode": "default"
},
"NetworkSettings": {
"Networks": {
"bridge": {
"NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID": "8b27c041c30326d59cd6e6f510d4f8d1d570a228466f956edf7815508f78e30d",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.6",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:06"
}
}
},
"Mounts": []
},
{
"Id": "4cb07b47f9fb",
"Names": [
"/running_cat"
],
"Image": "ubuntu:latest",
"ImageID": "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"State": "Exited",
"Status": "Exit 0",
"Ports": [],
"Labels": {},
"SizeRw": 12288,
"SizeRootFs": 0,
"HostConfig": {
"NetworkMode": "default"
},
"NetworkSettings": {
"Networks": {
"bridge": {
"NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID": "d91c7b2f0644403d7ef3095985ea0e2370325cd2332ff3a3225c4247328e66e9",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.5",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:05"
}
}
},
"Mounts": []
}
]
2. 获取exec执行id
POST
{http/https}://{host}:{port}/containers/{id}/exec
payload(application/json):
{
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"DetachKeys": "ctrl-p,ctrl-q",
"Tty": false,
"Cmd": [
"bash",
"-c",
"echo [base64 encrypted string] | base64 -d | sh"
],
"Env": [
"示例=示例",
"示例1=示例1"
]
}
响应:
{
"Id": "string"
}
3. 执行命令
POST
{http/https}://{host}:{port}/exec/{Id}/start
payload(application/json):
{
"Detach": false,
"Tty": true,
"ConsoleSize": [
80,
64
]
}
通过API可以实现远程批量执行脚本。
浙公网安备 33010602011771号