Contents

Docker Commonly Used Cmd

保证系统的纯净,移植常用开发工具到docker

docker常用命令

官方文档

docker run :创建一个新的容器并运行一个命令

docker exec :在运行的容器中执行命令

docker inspect : 获取容器/镜像的元数据。

我常用的alias:

1
2
3
alias d.ps='docker ps -a'
alias d.images='docker images'
alias d.stopall='docker stop $(docker ps -aq)'

ETCD

官方文档

1、创建容器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
REGISTRY=quay.io/coreos/etcd

DATA_DIR=/Users/XXX/dev/docker/etcd/

NODE1=0.0.0.0

docker run \
  -d \
  -p 2379:2379 \
  -p 2380:2380 \
  --volume=${DATA_DIR}:/etcd-data \
  --name etcd ${REGISTRY}:latest \
  /usr/local/bin/etcd \
  --data-dir=/etcd-data --name node1 \
  --initial-advertise-peer-urls http://${NODE1}:2380 --listen-peer-urls http://0.0.0.0:2380 \
  --advertise-client-urls http://${NODE1}:2379 --listen-client-urls http://0.0.0.0:2379 \
  --initial-cluster node1=http://${NODE1}:2380

2、进入容器shell

1
docker exec -it etcd /bin/sh

进入后就可以调用 etcdctl 进行设置 如:

1
2
etcdctl get config/stat_platform/online
etcdctl set /config/stat_platform/online '{"KafkaBrokerList":["192.168.10.8:32769"],"Listen":":8610","LogSetting":{"LogDir":"./logs","LogFile":"stat_platform.log","LogLevel":"DEBUG"}}'

mysql

容器文档

1
docker run -d -p 127.0.0.1:3306:3306 --name docker-mysql -v /Users/xxx/dev/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD="12345" mysql:5.7

mongo

容器文档

1
docker run --name docker-mongo -v /Users/xxx/dev/docker/mongo/db:/data/db -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD="12345" -d mongo

进入命令行

1
docker exec -it docker-mongo mongo -u "root" -p "12345" --authenticationDatabase "admin"

kafka

容器文档 参考

1、注意 KAFKA_ADVERTISED_HOST_NAME 要设置成本地IP 非localhost。

这里写了个脚本,每次动态获取本机IP,再创建容器运行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// get current ip
const os = require('os');
const interfaces = os.networkInterfaces();
const ips = [];
for (let key in interfaces) {
  interfaces[key].forEach(function(details) {
    if (details.family === 'IPv4' && !details.internal) {
				ips.push(details.address);
    }
  });
}
if (ips.length === 0) {
	throw Error('Get IP Failed!')
}
const chooseIp = ips[0];
console.log(`Current IP: ${ips}, Choose ${chooseIp}`);

// refresh config file
const fs = require('fs');
const REGEX = /\s?KAFKA_ADVERTISED_HOST_NAME/;
const readLines = [];
const configFile = '/Users/xxx/dev/docker/kafka/kafka-docker/docker-compose.yml';

fs.readFileSync(configFile, {encoding:'utf-8'})
	.split(/\r?\n/)
	.forEach(function (line) {
    let matches = REGEX.exec(line);
    if (matches) {
    	readLines.push(`${line.split(':')[0]}: ${chooseIp}`);
    } else {
    	readLines.push(line);
    }
  });

fs.writeFileSync(`${configFile}`, readLines.join('\n'));

// restart docker container
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function run() {
	const config = await exec('cat /Users/xxx/dev/docker/kafka/kafka-docker/docker-compose.yml;');
	console.log(config.stdout);

	const a = await exec('docker ps -a');
	console.log(a.stdout);

	await exec('cd /Users/xxx/dev/docker/kafka/kafka-docker; docker-compose stop; docker rm kafka-docker_zookeeper_1; docker rm kafka-docker_kafka_1;');
	
	await exec('cd /Users/xxx/dev/docker/kafka/kafka-docker; docker-compose up -d;');
	const b = await exec('docker ps -a');
	console.log(b.stdout);
}
run()

2、常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
启动/停止/增加broker:参考容器文档

进入容器:
docker exec -it kafka-docker_kafka_1 /bin/bash

进入后创建topic:注意这里的ip要和docker-compose.yml里的KAFKA_ADVERTISED_HOST_NAME一致,即上面脚本获取的IP。
kafka-topics.sh --create --zookeeper 192.168.22.29:2181 --replication-factor 1 --partitions 1 --topic event_topic

查看topic:IP同上
kafka-topics.sh --list --zookeeper 192.168.22.29:2181

发送消息:IP同上 端口通过d.ps查看kafka的本地映射端口
kafka-console-producer.sh --broker-list 192.168.22.29:32771 --topic event_topic

读取消息:
kafka-console-consumer.sh --zookeeper 192.168.22.29:2181 --topic event_topic --from-beginning

redis

文档

1
2
3
4
5
创建容器:
docker run --name docker-redis -p 6379:6379 -d -v /Users/xxx/dev/docker/redis/data:/data redis

进入命令行:
docker exec -it docker-redis redis-cli

nginx

文档

1
2
3
4
5
6
7
创建容器:
docker run --name docker-nginx -p 80:80 -d \
-v /Users/xxx/dev/docker/nginx:/etc/nginx \
nginx

进入命令行:
docker exec -it docker-nginx /bin/bash

注意:docker里连接本机的localhost,要换成其他方式

由于平时开发,nginx又要动态代理到本机localhost,所以任然保留了brew安装的版本 方便调试。

jenkins

文档

1
2
3
4
5
docker pull jenkins/jenkins
docker run -d -p 8080:8080 -p 50000:50000 -v jenkins_home:~/dev/docker/jenkins --name jenkins jenkins/jenkins
docker exec -it jenkins /bin/sh

fedomn:fedomn-admin

golang

这里简单示例,将floating-ticket-server打包到docker中 方便部署使用。

1、要修改代码bind的IP从127.0.0.1到0.0.0.0。

原因,127是一个回环地址,表示“我自己”,不能通过外部访问,只能自己访问

0.0.0.0 不能ping通,代表本机所有的IPV4地址。

2、增加Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
FROM golang:latest AS build-env

ADD . /src

RUN cd /src && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app

FROM scratch

COPY --from=build-env /src/app /

COPY --from=build-env /src/key /

EXPOSE 12345

ENTRYPOINT ["/app"]

可以看出,分成两步骤。最后执行打包运行:

1
2
3
docker build -t ticket .

docker run -d -p 12345:12345 --name ticket-server ticket

容器运行起来后,就可以通过外部localhost:12345进行访问了。

迁移注意

背景: Mac time machine迁移后 images都丢失了 Mac docker版本 Version 18.03.1-ce-mac65 (24312)

分析: Linux下容器在/var/lib/docker下,而Mac下容器都在 /Users/xxx/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux,主要都在Docker.qcow2里。

docker依赖Linux的cgroup,所以在mac上运行时候 会启动一个虚拟机中的Linux内核,同时 硬盘上存储一个qcow2格式的磁盘镜像文件。这个文件会随着Docker的使用不断膨胀,即使删除不用的Docker Image和Container也不会缩小。至少在这个版本官方还未解决。

网上有暴力的方法,先save image,再删除qcow2,最后load image。这种对于自己build的image可以使用。如果都是从官方hub里拉取的image,还是建议重新pull配置一下。毕竟也还是很简单的嘛,就是docker run一下。

坑: time machine备份的时候 没有备份/Users/xxx/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux这个目录。原因未知。

资料

DaoHub

官方Hub

Docker中文文档

Docker — 从入门到实践