在线免费托管docker的平台选择

  1. dockerhub,目前在用,由于其商业化策略导致的不可控变化,打算放弃
  2. github,Container Registry:因为访问不稳定和token的问题,暂时不考虑
  3. gitlab,Container Registry
  4. ECR, amazon出品,这里不考虑,因为账号体系的原因

所以暂时就一个可选项:gitlab

放一个相关的比较参考图:
file

github 容器注册服务器介绍

你可以在ghcr.io上存储和管理你的Docker和OCI镜像。

关于容器注册服务器支持类型

  • Docker Image Manifest V2, Schema2
  • Open Container Initiative 规格

容器服务器支持外部layer,比如windows 镜像。

登陆容器注册服务器

登陆ghcr.io建议使用GITHUB_TOKEN工作流来提高安全性。

  1. 创建一个PAT。设置好权限
  2. 建议将PAT设置为环境变量
    $ export CR_PAT=YOUR_TOKEN
  3. 通过CLI登陆容器注册服务器
    $ echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
    > Login Succeeded

发布容器镜像

$ docker push ghcr.io/OWNER/IMAGE_NAME:latest
or
$ docker push ghcr.io/OWNER/IMAGE-NAME:2.5

当第一次发布容器时,默认是私有的,需要改变可见性,需要自己去设置:Configuring a package's access control and visibility

获取镜像

通过digest获取精准镜像

  1. 获取digest,通过docker inspect或者docker pull命令,然后拷贝得到的SHA值
    $ docker inspect ghcr.io/OWNER/IMAGE_NAME
  2. 删除本地镜像
    $ docker rmi  ghcr.io/OWNER/IMAGE_NAME:latest
  3. 通过@YOUR_SHA_VALUE 获取精准的镜像
    $ docker pull ghcr.io/OWNER/IMAGE_NAME@sha256:82jf9a84u29hiasldj289498uhois8498hjs29hkuhs

通过名字

docker pull ghcr.io/OWNER/IMAGE_NAME

通过名字和版本

$ docker pull ghcr.io/OWNER/IMAGE_NAME:1.14.1

获取当前最新版

$ docker pull ghcr.io/OWNER/IMAGE_NAME:latest

编译镜像

$ docker build -t hello_docker .

tagging镜像

  1. 找到image id
    $ docker images
    > REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE
    > ghcr.io/my-org/hello_docker         latest              38f737a91f39        47 hours ago        91.7MB
    > ghcr.io/my-username/hello_docker    latest              38f737a91f39        47 hours ago        91.7MB
    > hello-world                                           latest              fce289e99eb9        16 months ago       1.84kB
  2. 通过ID和镜像名字和托管的主机来tag对应的镜像
    $ docker tag 38f737a91f39 ghcr.io/OWNER/NEW_IMAGE_NAME:latest

baota宝塔docker制作

这两天瞎折腾,因为数据库不一致的问题,一气之下把baota image删掉了,很多跟数据库相关的服务都歇了。

宝塔自用,在nas环境配合下数据库,搞个网络环境还是很方便的。

再重新拉取baota镜像时,发现怎么也访问不了,看日志,也没发现什么线索,所以才萌生了自己搞个docker的念头,主要是想定位下问题。

根据官方 www.bt.cn 最新的安装脚本制作了最新的 docker镜像:
https://gitlab.com/hiproz/baota-centos7-docker

特点:

  1. 和一般宝塔docker不同的是,采用延后安装的方式,支持将整个/www暴露出来,这样就可以将应用数据特别是数据库数据映射到用户空间,不至于不小心删除docker时,整个数据库数据丢失。
  2. 支持自动重新安装,如果系统发生未知问题,无法通过系统内更新,可以通过外部脚本的need_update 来更新。

docker的使用

docker run -tid --name baota --restart always -v /your-local-dir:/www -p your-local-port:8888 registry.gitlab.com/hiproz/baota-centos7-docker

安装进度日志

查看 run.log

默认登录路径和账号密码

查看映射路径下的default.txt, 注意要使用实际映射的端口,default.txt显示的是系统内部的端口。

如何修改已经创建docker的运行参数

update 命令

eg:

docker container update --restart=always 容器名字

修改container的配置文件

  • 先停止容器
  • 停止docker: systemctl stop docker
  • 修改配置文件,配置文件路径为/var/lib/docker/containers/容器ID,对应的配置文件为hostconfig.json和config.v2.json
  • 启动docker: systemctl start docker
  • 启动容器

注意,重启docker很重要,否则修改完的配置文件,重启容器后会被还原

Failed to get D-Bus connection: Operation not permitted

在docker中启用systemd时,过程中出现:
Failed to get D-Bus connection: Operation not permitted

原因

systemd维护系统服务程序,它需要特权去会访问Linux内核。而容器并不是一个完整的操作系统,只有一个文件系统,而且默认启动只是普通用户这样的权限访问Linux内核,也就是没有特权,所以自然就用不了!

解决

添加授权:
docker run -d -name centos7 --privileged=true centos:7 /usr/sbin/init

增加授权会提高风险,需要仔细评估具体的运行脚本和命令,避免对宿主造成安全风险

为什么有必要在docker中使用systemd

为什么要在docker中使用systemd

根据Walsh所说,容器中没有systemd最大的问题是它“退回到了使用初始化脚本之前。”每个镜像作者都在容器内创建自己的疯狂的启动脚本,而不是使用软件包作者精心制作的启动脚本。他演示了在具有systemd的容器内,服务初始化是何尝的简单,创建一个运行Apache httpd服务器的容器,其Dockerfile只有三行:

FROM fedora
RUN yum -y install httpd; yum clean all; systemctl enable httpd;
CMD [ "/sbin/init" ]

参考:
1. https://lwn.net/Articles/676831/ http://dockone.io/article/1093 (翻译)

docker软件安装

为了保持最精简的系统,默认的系统镜像是没有额外应用的,任何需要的应用几乎都要自己来安装。
默认docker使用的是宿主网卡,只可以直接访问外网的,如果访问外部网络有问题,请检查安装过程或者使用的镜像。

关于linux选用哪个系统好的问题,理论上hub.docker.com上各个官方的都差不多,哪个用的习惯就用那个。抛开具体的产品开发环境和团队系统要求,目前还是ubuntu的最多些。如果没有特殊要求,我们一般推荐ubuntu来做docker环境。

对于ubuntu新系统,第一步要 apt-get update,其他的系统同理。然后再安装其他需要的软件,否则可能提示找不到对应的包。

  1. ping
    apt-get install iputils-ping
    这个是必要的工具,方便来确认网络问题。

docker常用操作命令

  • 查询依赖

    docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=xxxxxx)

    xxxxxx标识的就是被依赖的image id

  • this deletes ALL STOPPED containers, images, volumes.

    docker system prune --all --volumes
  • 创建
    可以在hub.docker.com上创建一个新的repo,或者自己复制一个现有的repo.
    绑定github后,也可以直接通过Dockerfile来发生成最新的镜像

  • 查看镜像列表

    docker images
  • 查看容器列表

    docker ps
  • 查看所有的容器

    docker ps -a
  • 查看最近创建的容器

    docker ps -l
  • 查找在指定 image 之后创建的 image 中的父 image

    docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=xxxxxx)
  • 获取镜像

    docker pull name/reponame
  • 删除

    docker rm          Remove one or more containers
    docker rmi         Remove one or more images
  • 删除已经退出运行的容器

    docker ps -a | grep "Exited" | awk '{print $1 }'|xargs docker rm
  • 删除none镜像

    docker images |grep none |awk '{print $3}'|xargs docker rmi
  • 要删除全部image的话

    docker rmi $(docker images -q)
  • 停止所有容器
    停止容器,才能删除所包含的image

    docker stop $(docker ps -a -q)
  • ssh登录docker
    在开发阶段免不了需要ssh上去进行现场配置。
    从ssh启动docker:

    docker run -it  username/imagename /bin/bash

    ssh登陆,并挂载本地目录,默认读写权限:

    docker run -it -v 宿主绝对路径:docker绝对路径 username/imagename /bin/bash

    这样启动的入口进程是bash,整整需要启动的服务进程,再此模式下要自己手动启动

  • attach

    docker attach --sig-proxy=false $CONTAINER_ID

    如果当前的不是bash,attach上去也无法进行ssh,只有是上面这种直接启动ssh并后台运行的情况,attach上去,才进入ssh

  • exec
    在Docker1.3版本开始,提供了一个更方便的命令exec。可以直接在容器内运行命令。所以我们ssh登录docker最方便的是exec:

    docker exec -ti 7f16264f7ab4 /bin/bash
  • detach
    docker没有专用的命令,目前不能使用eixit,因为会导致主进程退出。使用ctl+p+ctl+q来detach当前的进程

  • 查看底层信息,比如IP等

    docker inspect --format='{{.NetworkSettings.IPAddress}}' $CONTAINER_ID
  • commit
    docker commit CONTAINER_ID docker_hub用户名/镜像名:tagname

  • push

    docker push docker_hub用户名/镜像名:tagname
  • docker hub的使用
    如果你使用hub.docker.com来管理你的镜像,那么就涉及到账户登录,如果你docker pull时遇到如下的提示:

    unauthorized: incorrect username or password

    那么说明你登录信息过期了,需要重新登录:

    docker login
  • 查看日志
    查看最新30分钟的日志:

    docker logs --since 30m CONTAINER_ID

    其他需求,请详细查看logs 的参数

  • 查看详细信息
    docker inspect id|name

  • 其他参考
    资深专家都知道的 Docker 常用命令---源英文:Top Docker Commands Any Expert Should Know
    Docker之容器的创建、启动、终止、删除、迁移等
    docker入门——构建镜像

关于DEBIAN_FRONTEND noninteractive的正确用法

DEBIAN_FRONTEND这个环境变量,告知操作系统应该从哪儿获得用户输入。如果设置为"noninteractive",你就可以直接运行命令,而无需向用户请求输入(所有操作都是非交互式的)。
这在运行apt-get命令的时候格外有用,因为它会不停的提示用户进行到了哪步并且需要不断确认。非交互模式会选择默认的选项并以最快的速度完成构建。
请确保只在Dockerfile中调用的RUN命令中设置了该选项,而不是使用ENV命令进行全局的设置。因为ENV命令在整个容器运行过程中都会生效,所以当你通过BASH和容器进行交互时,如果进行了全局设置那就会出问题。

正确的做法 - 只为这个命令设置ENV变量

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python3

错误地做法 - 为接下来的任何命令都设置ENV变量,包括正在运行地容器

ENV DEBIAN_FRONTEND noninteractive
RUN apt-get install -y python3

我的示例如下:

FROM ubuntu:trusty
MAINTAINER mryqu 
RUN \
 DEBIAN_FRONTEND=noninteractive apt-get update && \
 DEBIAN_FRONTEND=noninteractive apt-get -y install wget curl && \
 DEBIAN_FRONTEND=noninteractive apt-get -y autoremove && \
 DEBIAN_FRONTEND=noninteractive apt-get clean