Docker 和 iptables
如果你用 Docker 启动了一个服务暴露了一个端口,同时你又想通过 iptables 限制该端口的访问,这时候你按照经验往 INPUT 链插入一条规则发现并没有卵用,你应该看看 Docker 的官方文档 Docker and iptables 。这是因为 Docker 使用 iptables 提供网络隔离,只有在 DOCKER 和 DOCKER-USER 链上的规则才对容器暴露的端口生效,官方推荐用户在 DOCKER-USER 链上新增自定义规则。
使用 Docker 多阶段构建
自 Docker 17.05 Docker 开始支持多阶段构建,使用 Docker 多阶段构建有两个好处:
- 优化镜像大小
- 在镜像中排除源代码
比如一个典型的 Go 应用如果想要在镜像构建过程中编译,但是又不想镜像中包含源代码可以按照如下方式编写 Dockerfile
FROM golang:1.10 as intermediate
ENV PROJECT_PATH $GOPATH/src/github.com/coldnight/foobar
ADD . $PROJECT_PATH/
WORKDIR $PROJECT_PATH
RUN go install
FROM alpine:latest
COPY --from=intermediate /go/bin/foobar /go/bin/foobar
CMD ["/go/bin/foobar"]
具体使用方式参见官方文档 Use multi-stage builds 。
CMD vs ENTRYPOINT
我在一开始使用 Docker 时无法确定该使用 CMD 和 ENTRYPOINT 中的哪一个,其实很简单 CMD 可以在 docker run 时被覆盖,而 ENTRYPOINT 不可以,比如如下 Dockerfile:
FROM alpine:latest
CMD ['/bin/sh']
假设通过如下命令构建镜像:
$ docker build . -t demo
如果通过如下命令运行容器则默认启动 /bin/sh:
$ docker run -it demo
但如果想覆盖则可以通过如下方式运行容器:
$ docker run -it demo echo 'hello, world'
如果将 Dockerfile 中 CMD 替换为 ENTRYPOINT 则无法通过上述方式覆盖默认的启动命令。
Docker Web 管理系统
觉得手动敲命令管理本地 Docker 麻烦?可以试试本地安装一个 portainer ,通过 Web 界面管理本地 Docker。