标签 Docker 下的文章

Docker 是一个开源项目,为开发人员和系统管理员提供了一个开放平台,可以将应用程序构建、打包为一个轻量级容器,并在任何地方运行。Docker 会在软件容器中自动部署应用程序。

Django 是一个用 Python 编写的 Web 应用程序框架,遵循 MVC(模型-视图-控制器)架构。它是免费的,并在开源许可下发布。它速度很快,旨在帮助开发人员尽快将他们的应用程序上线。

在本教程中,我将逐步向你展示在 Ubuntu 16.04 中如何为现有的 Django 应用程序创建 docker 镜像。我们将学习如何 docker 化一个 Python Django 应用程序,然后使用一个 docker-compose 脚本将应用程序作为容器部署到 docker 环境。

为了部署我们的 Python Django 应用程序,我们需要其它 docker 镜像:一个用于 Web 服务器的 nginx docker 镜像和用于数据库的 PostgreSQL 镜像。

我们要做什么?

  1. 安装 Docker-ce
  2. 安装 Docker-compose
  3. 配置项目环境
  4. 构建并运行
  5. 测试

步骤 1 - 安装 Docker-ce

在本教程中,我们将从 docker 仓库安装 docker-ce 社区版。我们将安装 docker-ce 社区版和 docker-compose(其支持 compose 文件版本 3)。

在安装 docker-ce 之前,先使用 apt 命令安装所需的 docker 依赖项。

sudo apt install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

现在通过运行以下命令添加 docker 密钥和仓库。

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

安装 Docker-ce

更新仓库并安装 docker-ce。

sudo apt update
sudo apt install -y docker-ce

安装完成后,启动 docker 服务并使其能够在每次系统引导时启动。

systemctl start docker
systemctl enable docker

接着,我们将添加一个名为 omar 的新用户并将其添加到 docker 组。

useradd -m -s /bin/bash omar
usermod -a -G docker omar

启动 Docker

omar 用户身份登录并运行 docker 命令,如下所示。

su - omar
docker run hello-world

确保你能从 Docker 获得 hello-world 消息。

检查 Docker 安装

Docker-ce 安装已经完成。

步骤 2 - 安装 Docker-compose

在本教程中,我们将使用支持 compose 文件版本 3 的最新 docker-compose。我们将手动安装 docker-compose

使用 curl 命令将最新版本的 docker-compose 下载到 /usr/local/bin 目录,并使用 chmod 命令使其有执行权限。

运行以下命令:

sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

现在检查 docker-compose 版本。

docker-compose version

确保你安装的是最新版本的 docker-compose 1.21。

安装 Docker-compose

已安装支持 compose 文件版本 3 的 docker-compose 最新版本。

步骤 3 - 配置项目环境

在这一步中,我们将配置 Python Django 项目环境。我们将创建新目录 guide01,并使其成为我们项目文件的主目录,例如包括 Dockerfile、Django 项目、nginx 配置文件等。

登录到 omar 用户。

su - omar

创建一个新目录 guide01,并进入目录。

mkdir -p guide01
cd guide01/

现在在 guide01 目录下,创建两个新目录 projectconfig

mkdir project/ config/

注意:

  • project 目录:我们所有的 python Django 项目文件都将放在该目录中。
  • config 目录:项目配置文件的目录,包括 nginx 配置文件、python pip 的requirements.txt 文件等。

创建一个新的 requirements.txt 文件

接下来,使用 vim 命令在 config 目录中创建一个新的 requirements.txt 文件。

vim config/requirements.txt

粘贴下面的配置:

Django==2.0.4  
gunicorn==19.7.0  
psycopg2==2.7.4

保存并退出。

创建 Nginx 虚拟主机文件 django.conf

config 目录下创建 nginx 配置目录并添加虚拟主机配置文件 django.conf

mkdir -p config/nginx/
vim config/nginx/django.conf

粘贴下面的配置:

upstream web {
  ip_hash;
  server web:8000;
}
 
# portal
server {
  location / {
        proxy_pass http://web/;
  }
  listen 8000;
  server_name localhost;
 
  location /static {    
    autoindex on;    
    alias /src/static/;    
  }
}

保存并退出。

创建 Dockerfile

guide01 目录下创建新文件 Dockerfile

运行以下命令:

vim Dockerfile

现在粘贴下面的 Dockerfile 脚本:

FROM python:3.5-alpine
ENV PYTHONUNBUFFERED 1  

RUN apk update && \
    apk add --virtual build-deps gcc python-dev musl-dev && \
    apk add postgresql-dev bash

RUN mkdir /config  
ADD /config/requirements.txt /config/  
RUN pip install -r /config/requirements.txt
RUN mkdir /src
WORKDIR /src

保存并退出。

注意:

我们想要为我们的 Django 项目构建基于 Alpine Linux 的 Docker 镜像,Alpine 是最小的 Linux 版本。我们的 Django 项目将运行在带有 Python 3.5 的 Alpine Linux 上,并添加 postgresql-dev 包以支持 PostgreSQL 数据库。然后,我们将使用 python pip 命令安装在 requirements.txt 上列出的所有 Python 包,并为我们的项目创建新目录 /src

创建 Docker-compose 脚本

使用 vim 命令在 guide01 目录下创建 docker-compose.yml 文件。

vim docker-compose.yml

粘贴以下配置内容:

version: '3'
  services:
    db:
      image: postgres:10.3-alpine
      container_name: postgres01
    nginx:
      image: nginx:1.13-alpine
      container_name: nginx01
      ports:
        - "8000:8000"
      volumes:
        - ./project:/src
        - ./config/nginx:/etc/nginx/conf.d
      depends_on:
        - web
    web:
      build: .
      container_name: django01
      command: bash -c "python manage.py makemigrations && python manage.py migrate && python manage.py collectstatic --noinput && gunicorn hello_django.wsgi -b 0.0.0.0:8000"
      depends_on:
        - db
      volumes:
        - ./project:/src
      expose:
        - "8000"
      restart: always

保存并退出。

注意:

使用这个 docker-compose 文件脚本,我们将创建三个服务。使用 alpine Linux 版的 PostgreSQL 创建名为 db 的数据库服务,再次使用 alpine Linux 版的 Nginx 创建 nginx 服务,并使用从 Dockerfile 生成的自定义 docker 镜像创建我们的 python Django 容器。

配置项目环境

配置 Django 项目

将 Django 项目文件复制到 project 目录。

cd ~/django
cp -r * ~/guide01/project/

进入 project 目录并编辑应用程序设置 settings.py

cd ~/guide01/project/
vim hello_django/settings.py

注意:

我们将部署名为 “hello\_django” 的简单 Django 应用程序。

ALLOW_HOSTS 行中,添加服务名称 web

ALLOW_HOSTS = ['web']

现在更改数据库设置,我们将使用 PostgreSQL 数据库来运行名为 db 的服务,使用默认用户和密码。

DATABASES = {  
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
    }
}

至于 STATIC_ROOT 配置目录,将此行添加到文件行的末尾。

STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

保存并退出。

配置 Django 项目

现在我们准备在 docker 容器下构建和运行 Django 项目。

步骤 4 - 构建并运行 Docker 镜像

在这一步中,我们想要使用 guide01 目录中的配置为我们的 Django 项目构建一个 Docker 镜像。

进入 guide01 目录。

cd ~/guide01/

现在使用 docker-compose 命令构建 docker 镜像。

docker-compose build

运行 docker 镜像

启动 docker-compose 脚本中的所有服务。

docker-compose up -d

等待几分钟让 Docker 构建我们的 Python 镜像并下载 nginx 和 postgresql docker 镜像。

使用 docker-compose 构建镜像

完成后,使用以下命令检查运行容器并在系统上列出 docker 镜像。

docker-compose ps
docker-compose images

现在,你将在系统上运行三个容器,列出 Docker 镜像,如下所示。

docke-compose ps 命令

我们的 Python Django 应用程序现在在 docker 容器内运行,并且已经创建了为我们服务的 docker 镜像。

步骤 5 - 测试

打开 Web 浏览器并使用端口 8000 键入服务器地址,我的是:http://ovh01:8000/

现在你将看到默认的 Django 主页。

默认 Django 项目主页

接下来,通过在 URL 上添加 /admin 路径来测试管理页面。

http://ovh01:8000/admin/

然后你将会看到 Django 管理登录页面。

Django administration

Docker 化 Python Django 应用程序已成功完成。

参考


via: https://www.howtoforge.com/tutorial/docker-guide-dockerizing-python-django-application/

作者:Muhammad Arul 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用户名字空间 User Namespaces 于 Docker 1.10 版本正式纳入其中,该功能允许主机系统将自身的 uidgid 映射为容器进程中的另一个 uidgid。这对 Docker 的安全性来说是一项巨大的改进。下面我会通过一个案例来展示一下用户名字空间能够解决的问题,以及如何启用该功能。

创建一个 Docker Machine

如果你已经创建好了一台用来试验用户名字空间的 docker 机器 Machine ,那么可以跳过这一步。我在自己的 Macbook 上安装了 Docker Toolbox,因此我只需用 docker-machine 命令就很简单地创建一个基于 VirtualBox 的 Docker 机器(这里假设主机名为 host1):

# Create host1
$ docker-machine create --driver virtualbox host1

# Login to host1
$ docker-machine ssh host1

理解在用户名字空间未启用的情况下,非 root 用户能做什么

在启用用户名字空间前,我们先来看一下会有什么问题。Docker 到底哪个地方做错了?首先,使用 Docker 的一大优势在于用户在容器中可以拥有 root 权限,因此用户可以很方便地安装软件包。但是在 Linux 容器技术中这也是一把双刃剑。只要经过少许操作,非 root 用户就能以 root 的权限访问主机系统中的内容,比如 /etc。下面是操作步骤。

# Run a container and mount host1's /etc onto /root/etc
$ docker run --rm -v /etc:/root/etc -it ubuntu

# Make some change on /root/etc/hosts
root@34ef23438542:/# vi /root/etc/hosts

# Exit from the container
root@34ef23438542:/# exit

# Check /etc/hosts
$ cat /etc/hosts

你可以看到,步骤简单到难以置信,很明显 Docker 并不适用于运行在多人共享的电脑上。但是现在,通过用户名字空间,Docker 可以避免这个问题。

启用用户名字空间

# Create a user called "dockremap"
$ sudo adduser dockremap

# Setup subuid and subgid
$ sudo sh -c 'echo dockremap:500000:65536 > /etc/subuid'
$ sudo sh -c 'echo dockremap:500000:65536 > /etc/subgid'

然后,打开 /etc/init.d/docker,并在 /usr/local/bin/docker daemon 后面加上 --userns-remap=default,像这样:

$ sudo vi /etc/init.d/docker

/usr/local/bin/docker daemon --userns-remap=default -D -g "$DOCKER_DIR" -H unix:// $DOCKER_HOST $EXTRA_ARGS >> "$DOCKER_LOGFILE" 2>&1 &

然后重启 Docker:

$ sudo /etc/init.d/docker restart

这就完成了!

注意:若你使用的是 CentOS 7,则你需要了解两件事。

  1. 内核默认并没有启用用户名字空间。运行下面命令并重启系统,可以启用该功能。
sudo grubby --args="user_namespace.enable=1" \
    --update-kernel=/boot/vmlinuz-3.10.0-XXX.XX.X.el7.x86_64
  1. CentOS 7 使用 systemctl 来管理服务,因此你需要编辑的文件是 /usr/lib/systemd/system/docker.service

确认用户名字空间是否正常工作

若一切都配置妥当,则你应该无法再在容器中编辑 host1 上的 /etc 了。让我们来试一下。

# Create a container and mount host1's /etc to container's /root/etc
$ docker run --rm -v /etc:/root/etc -it ubuntu

# Check the owner of files in /root/etc, which should be "nobody nogroup".
root@d5802c5e670a:/# ls -la /root/etc
total 180
drwxr-xr-x 11 nobody nogroup 1100 Mar 21 23:31 .
drwx------ 3 root root 4096 Mar 21 23:50 ..
lrwxrwxrwx 1 nobody nogroup 19 Mar 21 23:07 acpi -> /usr/local/etc/acpi
-rw-r--r-- 1 nobody nogroup 48 Mar 10 22:09 boot2docker
drwxr-xr-x 2 nobody nogroup 60 Mar 21 23:07 default

# Try creating a file in /root/etc
root@d5802c5e670a:/# touch /root/etc/test
touch: cannot touch '/root/etc/test': Permission denied

# Try deleting a file
root@d5802c5e670a:/# rm /root/etc/hostname
rm: cannot remove '/root/etc/hostname': Permission denied

好了,太棒了。这就是用户名字空间的工作方式。


via: https://coderwall.com/p/s_ydlq/using-user-namespaces-on-docker

作者:Koji Tanaka 选题:lujun9972 译者:lujun9972 校对:pityonline

本文由 LCTT 原创编译,Linux中国 荣誉推出

Buildah 提供一种灵活、可脚本编程的方式,来使用你熟悉的工具创建精简、高效的容器镜像。

Buildah 是一个命令行工具,可以方便、快捷的构建与 开放容器标准 Open Container Initiative (OCI)兼容的容器镜像,这意味着其构建的镜像与 Docker 和 Kubernetes 兼容。该工具可作为 Docker 守护进程 docker build 命令(即使用传统的 Dockerfile 构建镜像)的一种 简单 drop-in 替换,而且更加灵活,允许构建镜像时使用你擅长的工具。Buildah 可以轻松与脚本集成并生成 流水线 pipeline ,最好之处在于构建镜像不再需要运行容器守护进程(LCTT 译注:这里主要是指 Docker 守护进程)。

docker build 的简单替换

目前你可能使用 Dockerfile 和 docker build 命令构建镜像,那么你可以马上使用 Buildah 进行替代。Buildah 的 build-using-dockerfile (或 bud)子命令与 docker build 基本等价,因此可以轻松的与已有脚本结合或构建流水线。

类似我的上一篇关于 Buildah 的文章,我也将以使用源码安装 “GNU Hello” 为例进行说明,对应的 Dockerfile 文件如下:

FROM fedora:28
LABEL maintainer Chris Collins <[email protected]>

RUN dnf install -y tar gzip gcc make \
        && dnf clean all

ADD http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz /tmp/hello-2.10.tar.gz

RUN tar xvzf /tmp/hello-2.10.tar.gz -C /opt

WORKDIR /opt/hello-2.10

RUN ./configure
RUN make
RUN make install
RUN hello -v
ENTRYPOINT "/usr/local/bin/hello"

使用 Buildah 从 Dockerfile 构建镜像也很简单,使用 buildah bud -t hello . 替换 docker build -t hello . 即可:

[chris@krang] $ sudo buildah bud -t hello .
STEP 1: FROM fedora:28
Getting image source signatures
Copying blob sha256:e06fd16225608e5b92ebe226185edb7422c3f581755deadf1312c6b14041fe73
 81.48 MiB / 81.48 MiB [====================================================] 8s
Copying config sha256:30190780b56e33521971b0213810005a69051d720b73154c6e473c1a07ebd609
 2.29 KiB / 2.29 KiB [======================================================] 0s
Writing manifest to image destination
Storing signatures
STEP 2: LABEL maintainer Chris Collins <[email protected]>
STEP 3: RUN dnf install -y tar gzip gcc make    && dnf clean all

<考虑篇幅,略去后续输出>

镜像构建完毕后,可以使用 buildah images 命令查看这个新镜像:

[chris@krang] $ sudo buildah images
IMAGE ID        IMAGE NAME                              CREATED AT              SIZE
30190780b56e    docker.io/library/fedora:28             Mar 7, 2018 16:53       247 MB
6d54bef73e63    docker.io/library/hello:latest    May 3, 2018 15:24     391.8 MB

新镜像的标签为 hello:latest,我们可以将其推送至远程镜像仓库,可以使用 CRI-O 或其它 Kubernetes CRI 兼容的运行时来运行该镜像,也可以推送到远程仓库。如果你要测试对 Docker build 命令的替代性,你可以将镜像拷贝至 docker 守护进程的本地镜像存储中,这样 Docker 也可以使用该镜像。使用 buildah push 可以很容易的完成推送操作:

[chris@krang] $ sudo buildah push hello:latest docker-daemon:hello:latest
Getting image source signatures
Copying blob sha256:72fcdba8cff9f105a61370d930d7f184702eeea634ac986da0105d8422a17028
 247.02 MiB / 247.02 MiB [==================================================] 2s
Copying blob sha256:e567905cf805891b514af250400cc75db3cb47d61219750e0db047c5308bd916
 144.75 MiB / 144.75 MiB [==================================================] 1s
Copying config sha256:6d54bef73e638f2e2dd8b7bf1c4dfa26e7ed1188f1113ee787893e23151ff3ff
 1.59 KiB / 1.59 KiB [======================================================] 0s
Writing manifest to image destination
Storing signatures

[chris@krang] $ sudo docker images | head -n2
REPOSITORY              TAG             IMAGE ID        CREATED                 SIZE
docker.io/hello      latest       6d54bef73e63  2 minutes ago   398 MB

[chris@krang] $ sudo docker run -t hello:latest
Hello, world!

若干差异

与 Docker build 不同,Buildah 不会自动的将 Dockerfile 中的每条指令产生的变更提到新的 分层 layer 中,只是简单的每次从头到尾执行构建。类似于 自动化 automation 流水线构建 build pipeline ,这种 无缓存构建 non-cached 方式的好处是可以提高构建速度,在指令较多时尤为明显。从 自动部署 automated deployment 持续交付 continuous delivery 的视角来看,使用这种方式可以快速的将新变更落实到生产环境中。

但从实际角度出发,缓存机制的缺乏对镜像开发不利,毕竟缓存层可以避免一遍遍的执行构建,从而显著的节省时间。自动分层只在 build-using-dockerfile 命令中生效。但我们在下面会看到,Buildah 原生命令允许我们选择将变更提交到硬盘的时间,提高了开发的灵活性。

Buildah 原生命令

Buildah 真正 有趣之处在于它的原生命令,你可以在容器构建过程中使用这些命令进行交互。相比与使用 build-using-dockerfile/bud 命令执行每次构建,Buildah 提供命令让你可以与构建过程中的临时容器进行交互。(Docker 也使用临时或 中间 intermediate 容器,但你无法在镜像构建过程中与其交互。)

还是使用 “GNU Hello” 为例,考虑使用如下 Buildah 命令构建的镜像:

#!/usr/bin/env bash

set -o errexit

# Create a container
container=$(buildah from fedora:28)

# Labels are part of the "buildah config" command
buildah config --label maintainer="Chris Collins <[email protected]>" $container

# Grab the source code outside of the container
curl -sSL http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz -o hello-2.10.tar.gz

buildah copy $container hello-2.10.tar.gz /tmp/hello-2.10.tar.gz

buildah run $container dnf install -y tar gzip gcc make
buildah run $container dnf clean all
buildah run $container tar xvzf /tmp/hello-2.10.tar.gz -C /opt

# Workingdir is also a "buildah config" command
buildah config --workingdir /opt/hello-2.10 $container

buildah run $container ./configure
buildah run $container make
buildah run $container make install
buildah run $container hello -v

# Entrypoint, too, is a “buildah config” command
buildah config --entrypoint /usr/local/bin/hello $container

# Finally saves the running container to an image
buildah commit --format docker $container hello:latest

我们可以一眼看出这是一个 Bash 脚本而不是 Dockerfile。基于 Buildah 的原生命令,可以轻易的使用任何脚本语言或你擅长的自动化工具编写脚本。形式可以是 makefile、Python 脚本或其它你擅长的类型。

这个脚本做了哪些工作呢?首先,Buildah 命令 container=$(buildah from fedora:28) 基于 fedora:28 镜像创建了一个正在运行的容器,将容器名(buildah from 命令的返回值)保存到变量中,便于后续使用。后续所有命令都是有 $container 变量指明需要操作的容器。这些命令的功能大多可以从名称看出:buildah copy 将文件拷贝至容器,buildah run 会在容器中执行命令。可以很容易的将上述命令与 Dockerfile 中的指令对应起来。

最后一条命令 buildah commit 将容器提交到硬盘上的镜像中。当不使用 Dockerfile 而是使用 Buildah 命令构建镜像时,你可以使用 commit 命令决定何时保存变更。在上例中,所有的变更是一起提交的;但也可以增加中间提交,让你可以选择作为起点的 缓存点 cache point 。(例如,执行完 dnf install 命令后将变更缓存到硬盘是特别有意义的,一方面因为该操作耗时较长,另一方面每次执行的结果也确实相同。)

挂载点,安装目录以及 chroot

另一个可以大大增加构建镜像灵活性的 Buildah 命令是 buildah mount,可以将容器的根目录挂载到你主机的一个挂载点上。例如:

[chris@krang] $ container=$(sudo buildah from fedora:28)
[chris@krang] $ mountpoint=$(sudo buildah mount ${container})
[chris@krang] $ echo $mountpoint
/var/lib/containers/storage/overlay2/463eda71ec74713d8cebbe41ee07da5f6df41c636f65139a7bd17b24a0e845e3/merged
[chris@krang] $ cat ${mountpoint}/etc/redhat-release
Fedora release 28 (Twenty Eight)
[chris@krang] $ ls ${mountpoint}
bin   dev  home  lib64          media  opt   root  sbin  sys  usr
boot  etc  lib   lost+found  mnt        proc  run   srv   tmp  var

这太棒了,你可以通过与挂载点交互对容器镜像进行修改。这允许你使用主机上的工具进行构建和安装软件,不用将这些构建工具打包到容器镜像本身中。例如,在我们上面的 Bash 脚本中,我们需要安装 tar、Gzip、GCC 和 make,在容器内编译 “GNU Hello”。如果使用挂载点,我仍使用同样的工具进行构建,但下载的压缩包和 tar、Gzip 等 RPM 包都在主机而不是容器和生成的镜像内:

#!/usr/bin/env bash

set -o errexit

# Create a container
container=$(buildah from fedora:28)
mountpoint=$(buildah mount $container)

buildah config --label maintainer="Chris Collins <[email protected]>" $container

curl -sSL http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz \
     -o /tmp/hello-2.10.tar.gz
tar xvzf src/hello-2.10.tar.gz -C ${mountpoint}/opt

pushd ${mountpoint}/opt/hello-2.10
./configure
make
make install DESTDIR=${mountpoint}
popd

chroot $mountpoint bash -c "/usr/local/bin/hello -v"

buildah config --entrypoint "/usr/local/bin/hello" $container
buildah commit --format docker $container hello
buildah unmount $container

在上述脚本中,需要提到如下几点:

  1. curl 命令将压缩包下载到主机中,而不是镜像中;
  2. (主机中的) tar 命令将压缩包中的源代码解压到容器的 /opt 目录;
  3. configuremakemake install 命令都在主机的挂载点目录中执行,而不是在容器内;
  4. 这里的 chroot 命令用于将挂载点本身当作根路径并测试 "hello" 是否正常工作;类似于前面例子中用到的 buildah run 命令。

这个脚本更加短小,使用大多数 Linux 爱好者都很熟悉的工具,最后生成的镜像也更小(没有 tar 包,没有额外的软件包等)。你甚至可以使用主机系统上的包管理器为容器安装软件。例如,(出于某种原因)你希望安装 GNU Hello 的同时在容器中安装 NGINX

[chris@krang] $ mountpoint=$(sudo buildah mount ${container})
[chris@krang] $ sudo dnf install nginx --installroot $mountpoint
[chris@krang] $ sudo chroot $mountpoint nginx -v
nginx version: nginx/1.12.1

在上面的例子中,DNF 使用 --installroot 参数将 NGINX 安装到容器中,可以通过 chroot 进行校验。

快来试试吧!

Buildah 是一种轻量级、灵活的容器镜像构建方法,不需要在主机上运行完整的 Docker 守护进程。除了提供基于 Dockerfile 构建容器的开箱即用支持,Buildah 还可以很容易的与脚本或你喜欢的构建工具相结合,特别是可以使用主机上已有的工具构建容器镜像。Buildah 生成的容器体积更小,更便于网络传输,占用更小的存储空间,而且潜在的受攻击面更小。快来试试吧!

阅读相关的故事,[使用 Buildah 创建小体积的容器]


via: https://opensource.com/article/18/6/getting-started-buildah

作者:Chris Collins 选题:lujun9972 译者:pinewall 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在前一篇文章中,我们谈到了 容器 container 是什么以及它是如何培育创新并助力企业快速发展的。在以后的文章中,我们将讨论如何使用容器。然而,在深入探讨这个话题之前,我们需要了解关于容器的一些术语和命令。掌握了这些术语,才不至于产生混淆。

让我们来探讨 Docker 容器世界中使用的一些基本术语吧。

容器 Container :到底什么是容器呢?它是一个 Docker 镜像 image 的运行实例。它包含一个 Docker 镜像、执行环境和说明。它与系统完全隔离,所以可以在系统上运行多个容器,并且完全无视对方的存在。你可以从同一镜像中复制出多个容器,并在需求较高时扩展服务,在需求低时对这些容器进行缩减。

Docker 镜像 Image :这与你下载的 Linux 发行版的镜像别无二致。它是一个安装包,包含了用于创建、部署和执行容器的一系列依赖关系和信息。你可以在几秒钟内创建任意数量的完全相同的容器。镜像是分层叠加的。一旦镜像被创建出来,是不能更改的。如果你想对容器进行更改,则只需创建一个新的镜像并从该镜像部署新的容器即可。

仓库 Repository (repo):Linux 的用户对于仓库这个术语一定不陌生吧。它是一个软件库,存储了可下载并安装在系统中的软件包。在 Docker 容器中,唯一的区别是它管理的是通过标签分类的 Docker 镜像。你可以找到同一个应用程序的不同版本或不同变体,他们都有适当的标记。

镜像管理服务 Registry :可以将其想象成 GitHub。这是一个在线服务,管理并提供了对 Docker 镜像仓库的访问,例如默认的公共镜像仓库——DockerHub。供应商可以将他们的镜像库上传到 DockerHub 上,以便他们的客户下载和使用官方镜像。一些公司为他们的镜像提供自己的服务。镜像管理服务不必由第三方机构来运行和管理。组织机构可以使用预置的服务来管理内部范围的镜像库访问。

标签 Tag :当你创建 Docker 镜像时,可以给它添加一个合适的标签,以便轻松识别不同的变体或版本。这与你在任何软件包中看到的并无区别。Docker 镜像在添加到镜像仓库时被标记。

现在你已经掌握了基本知识,下一个阶段是理解实际使用 Docker 容器时用到的术语。

Dockerfile :这是一个文本文件,包含为了为构建 Docker 镜像需手动执行的命令。Docker 使用这些指令自动构建镜像。

构建 Build :这是从 Dockerfile 创建成镜像的过程。

推送 Push :一旦镜像创建完成,“push” 是将镜像发布到仓库的过程。该术语也是我们下一篇文章要学习的命令之一。

拉取 Pull :用户可以通过 “pull” 过程从仓库检索该镜像。

编组 Compose :复杂的应用程序会包含多个容器。docker-compose 是一个用于运行多容器应用程序的命令行工具。它允许你用单条命令运行一个多容器的应用程序,简化了多容器带来的问题。

总结

容器术语的范围很广泛,这里是经常遇到的一些基本术语。下一次当你看到这些术语时,你会确切地知道它们的含义。在下一篇文章中,我们将开始使用 Docker 容器。


via: https://www.linux.com/blog/intro-to-linux/2017/12/container-basics-terms-you-need-know

作者:Swapnil Bhartiya 译者:jessie-pang 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

按照这些简单的步骤在你的 Linux、Mac 或 Windows 桌面上安装 Docker CE。

在上一篇文章中,我们学习了容器世界的一些基本术语。当我们运行命令并在后续文章中使用其中一些术语时,这些背景信息将会派上用场,包括这篇文章。本文将介绍在桌面 Linux、 macOS 和 Windows 上安装 Docker,它适用于想要开始使用 Docker 容器的初学者。唯一的先决条件是你对命令行界面满意。

为什么我在本地机器上需要 Docker CE?

作为一个新用户,你很可能想知道为什么你在本地系统上需要容器。难道它们不是作为微服务在云和服务器中运行吗?尽管容器长期以来一直是 Linux 世界的一部分,但 Docker 才真正使容器的工具和技术步入使用。

Docker 容器最大的优点是可以使用本地机器进行开发和测试。你在本地系统上创建的容器映像可以在“任何位置”运行。开发人员和操作人员之间不再会为应用程序在开发系统上运行良好但生产环境中出现问题而产生纷争。

而这个关键是,要创建容器化的应用程序,你必须能够在本地系统上运行和创建容器。

你可以使用以下三个平台中的任何一个 —— 桌面 Linux、 Windows 或 macOS 作为容器的开发平台。一旦 Docker 在这些系统上成功运行,你将可以在不同的平台上使用相同的命令。因此,接下来你运行的操作系统无关紧要。

这就是 Docker 之美。

让我们开始吧

现在有两个版本的 Docker:Docker 企业版(EE)和 Docker 社区版(CE)。我们将使用 Docker 社区版,这是一个免费的 Docker 版本,面向想要开始使用 Docker 的开发人员和爱好者。

Docker CE 有两个版本:stable 和 edge。顾名思义,stable(稳定)版本会为你提供经过充分测试的季度更新,而 edge 版本每个月都会提供新的更新。经过进一步的测试之后,这些边缘特征将被添加到稳定版本中。我建议新用户使用 stable 版本。

Docker CE 支持 macOS、 Windows 10、 Ubuntu 14.04/16.04/17.04/17.10、 Debian 7.7/8/9/10、 Fedora 25/26/27 和 CentOS。虽然你可以下载 Docker CE 二进制文件并安装到桌面 Linux 上,但我建议添加仓库源以便继续获得修补程序和更新。

在桌面 Linux 上安装 Docker CE

你不需要一个完整的桌面 Linux 来运行 Docker,你也可以将它安装在最小的 Linux 服务器上,即你可以在一个虚拟机中运行。在本教程中,我将在我的主系统的 Fedora 27 和 Ubuntu 17.04 上运行它。

在 Ubuntu 上安装

首先,运行系统更新,以便你的 Ubuntu 软件包完全更新:

$ sudo apt-get update

现在运行系统升级:

$ sudo apt-get dist-upgrade

然后安装 Docker PGP 密钥:

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Update the repository info again:
$ sudo apt-get update

现在安装 Docker CE:

$ sudo apt-get install docker-ce

一旦安装完成,Docker CE 就会在基于 Ubuntu 的系统上自动运行,让我们来检查它是否在运行:

$ sudo systemctl status docker

你应该得到以下输出:

docker.service - Docker Application Container Engine
  Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
  Active: active (running) since Thu 2017-12-28 15:06:35 EST; 19min ago
    Docs: https://docs.docker.com
Main PID: 30539 (dockerd)

由于 Docker 安装在你的系统上,你现在可以使用 Docker CLI(命令行界面)运行 Docker 命令。像往常一样,我们运行 ‘Hello World’ 命令:

$ sudo docker run hello-world

恭喜!在你的 Ubuntu 系统上正在运行着 Docker。

在 Fedora 上安装 Docker CE

Fedora 27 上的情况有些不同。在 Fedora 上,你首先需要安装 def-plugins-core 包,这将允许你从 CLI 管理你的 DNF 包。

$ sudo dnf -y install dnf-plugins-core

现在在你的系统上安装 Docker 仓库:

$ sudo dnf config-manager \
    --add-repo \
    https://download.docker.com/linux/fedora/docker-ce.repo
It’s time to install Docker CE:
$ sudo dnf install docker-ce

与 Ubuntu 不同,Docker 不会在 Fedora 上自动启动。那么让我们启动它:

$ sudo systemctl start docker

你必须在每次重新启动后手动启动 Docker,因此让我们将其配置为在重新启动后自动启动。$ systemctl enable docker 就行。现在该运行 Hello World 命令了:

$ sudo docker run hello-world

恭喜,在你的 Fedora 27 系统上正在运行着 Docker。

解除 root

你可能已经注意到你必须使用 sudo 来运行 docker 命令。这是因为 Docker 守护进程与 UNIX 套接字绑定,而不是 TCP 端口,套接字由 root 用户拥有。所以,你需要 sudo 权限才能运行 docker 命令。你可以将系统用户添加到 docker 组,这样它就不需要 sudo 了:

$ sudo groupadd docker

在大多数情况下,在安装 Docker CE 时会自动创建 Docker 用户组,因此你只需将用户添加到该组中即可:

$ sudo usermod -aG docker $USER

为了测试该组是否已经成功添加,根据用户名运行 groups 命令:

$ groups swapnil

(这里,swapnil 是用户名。)

这是在我系统上的输出:

swapnil : swapnil adm cdrom sudo dip plugdev lpadmin sambashare docker

你可以看到该用户也属于 docker 组。注销系统,这样组就会生效。一旦你再次登录,在不使用 sudo 的情况下试试 Hello World 命令:

$ docker run hello-world

你可以通过运行以下命令来查看关于 Docker 的安装版本以及更多系统信息:

$ docker info

在 macOS 和 Windows 上安装 Docker CE

你可以在 macOS 和 Windows 上很轻松地安装 Docker CE(和 EE)。下载官方为 macOS 提供的 Docker 安装包,在 macOS 上安装应用程序的方式是只需将它们拖到 Applications 目录即可。一旦文件被复制,从 spotlight(LCTT 译注:mac 下的搜索功能)下打开 Docker 开始安装。一旦安装,Docker 将自动启动,你可以在 macOS 的顶部看到它。

macOS 是类 UNIX 系统,所以你可以简单地打开终端应用程序,并开始使用 Docker 命令。测试 hello world 应用:

$ docker run hello-world

恭喜,你已经在你的 macOS 上运行了 Docker。

在 Windows 10 上安装 Docker

你需要最新版本的 Windows 10 Pro 或 Server 才能在它上面安装或运行 Docker。如果你没有完全更新,Windows 将不会安装 Docker。我在 Windows 10 系统上遇到了错误,必须运行系统更新。我的版本还很落后,我出现了这个 bug。所以,如果你无法在 Windows 上安装 Docker,只要知道并不是只有你一个。仔细检查该 bug 以找到解决方案。

一旦你在 Windows 上安装 Docker 后,你可以通过 WSL 使用 bash shell,或者使用 PowerShell 来运行 Docker 命令。让我们在 PowerShell 中测试 “Hello World” 命令:

PS C:\Users\swapnil> docker run hello-world

恭喜,你已经在 Windows 上运行了 Docker。

在下一篇文章中,我们将讨论如何从 DockerHub 中拉取镜像并在我们的系统上运行容器。我们还会讨论推送我们自己的容器到 Docker Hub。


via: https://www.linux.com/blog/learn/intro-to-linux/how-install-docker-ce-your-desktop

作者:SWAPNIL BHARTIYA 选题:lujun9972 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

利用这 8 个命令可以学习 Docker 容器的基本管理方式。这是一个为 Docker 初学者准备的,带有示范命令输出的指南。

Docker 容器管理命令

在这篇文章中,我们将带你学习 8 个基本的 Docker 容器命令,它们操控着 Docker 容器的基本活动,例如 运行 run 列举 list 停止 stop 、 查看 历史纪录 logs 删除 delete 等等。如果你对 Docker 的概念很陌生,推荐你看看我们的 介绍指南,来了解 Docker 的基本内容以及 如何 在 Linux 上安装 Docker。 现在让我们赶快进入要了解的命令:

如何运行 Docker 容器?

众所周知,Docker 容器只是一个运行于 宿主操作系统 host OS 上的应用进程,所以你需要一个镜像来运行它。Docker 镜像以进程的方式运行时就叫做 Docker 容器。你可以加载本地 Docker 镜像,也可以从 Docker Hub 上下载。Docker Hub 是一个提供公有和私有镜像来进行 拉取 pull 操作的集中仓库。官方的 Docker Hub 位于 hub.docker.com。 当你指示 Docker 引擎运行容器时,它会首先搜索本地镜像,如果没有找到,它会从 Docker Hub 上拉取相应的镜像。

让我们运行一个 Apache web 服务器的 Docker 镜像,比如 httpd 进程。你需要运行 docker container run 命令。旧的命令为 docker run, 但后来 Docker 添加了子命令部分,所以新版本支持下列命令:

root@kerneltalks # docker container run -d -p 80:80 httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
3d77ce4481b1: Pull complete
73674f4d9403: Pull complete
d266646f40bd: Pull complete
ce7b0dda0c9f: Pull complete
01729050d692: Pull complete
014246127c67: Pull complete
7cd2e04cf570: Pull complete
Digest: sha256:f4610c3a1a7da35072870625733fd0384515f7e912c6223d4a48c6eb749a8617
Status: Downloaded newer image for httpd:latest
c46f2e9e4690f5c28ee7ad508559ceee0160ac3e2b1688a61561ce9f7d99d682

Docker 的 run 命令将镜像名作为强制参数,另外还有很多可选参数。常用的参数有:

  • -d:从当前 shell 脱离容器
  • -p X:Y:绑定容器的端口 Y 到宿主机的端口 X
  • --name:命名你的容器。如果未指定,它将被赋予随机生成的名字
  • -e:当启动容器时传递环境编辑及其值

通过以上输出你可以看到,我们将 httpd 作为镜像名来运行容器。接着,本地镜像没有找到,Docker 引擎从 Docker Hub 拉取了它。注意,它下载了镜像 httpd:latest, 其中 : 后面跟着版本号。如果你需要运行特定版本的容器,你可以在镜像名后面注明版本名。如果不提供版本名,Docker 引擎会自动拉取最新的版本。

输出的最后一行显示了你新运行的 httpd 容器的唯一 ID。

如何列出所有运行中的 Docker 容器?

现在,你的容器已经运行起来了,你可能想要确认这一点,或者你想要列出你的机器上运行的所有容器。你可以使用 docker container ls 命令。在旧的 Docker 版本中,对应的命令为 docker ps

root@kerneltalks # docker container ls
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                NAMES
c46f2e9e4690        httpd               "httpd-foreground"   11 minutes ago      Up 11 minutes       0.0.0.0:80->80/tcp   cranky_cori

列出的结果是按列显示的。每一列的值分别为:

  1. Container ID :一开始的几个字符对应你的容器的唯一 ID
  2. Image :你运行容器的镜像名
  3. Command :容器启动后运行的命令
  4. Created :创建时间
  5. Status :容器当前状态
  6. Ports :与宿主端口相连接的端口信息
  7. Names :容器名(如果你没有命名你的容器,那么会随机创建)

如何查看 Docker 容器的历史纪录?

在第一步我们使用了 -d 参数来将容器,在它一开始运行的时候,就从当前的 shell 中脱离出来。在这种情况下,我们不知道容器里面发生了什么。所以为了查看容器的历史纪录,Docker 提供了 logs 命令。它采用容器名称或 ID 作为参数。

root@kerneltalks # docker container logs cranky_cori
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Thu May 31 18:35:07.301158 2018] [mpm_event:notice] [pid 1:tid 139734285989760] AH00489: Apache/2.4.33 (Unix) configured -- resuming normal operations
[Thu May 31 18:35:07.305153 2018] [core:notice] [pid 1:tid 139734285989760] AH00094: Command line: 'httpd -D FOREGROUND'

这里我使用了容器名称作为参数。你可以看到在我们的 httpd 容器中与 Apache 相关的历史纪录。

如何确定 Docker 容器的进程?

容器是一个使用宿主资源来运行的进程。这样,你可以在宿主系统的进程表中定位容器的进程。让我们在宿主系统上确定容器进程。

Docker 使用著名的 top 命令作为子命令的名称,来查看容器产生的进程。它采用容器的名称或 ID 作为参数。在旧版本的 Docker 中,只可运行 docker top 命令。在新版本中,docker topdocker container top 命令都可以生效。

root@kerneltalks # docker container top  cranky_cori
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                15702               15690               0                   18:35               ?                   00:00:00            httpd -DFOREGROUND
bin                 15729               15702               0                   18:35               ?                   00:00:00            httpd -DFOREGROUND
bin                 15730               15702               0                   18:35               ?                   00:00:00            httpd -DFOREGROUND
bin                 15731               15702               0                   18:35               ?                   00:00:00            httpd -DFOREGROUND

root@kerneltalks # ps -ef |grep -i 15702
root     15702 15690  0 18:35 ?        00:00:00 httpd -DFOREGROUND
bin      15729 15702  0 18:35 ?        00:00:00 httpd -DFOREGROUND
bin      15730 15702  0 18:35 ?        00:00:00 httpd -DFOREGROUND
bin      15731 15702  0 18:35 ?        00:00:00 httpd -DFOREGROUND
root     15993 15957  0 18:59 pts/0    00:00:00 grep --color=auto -i 15702

在第一个输出中,列出了容器产生的进程的列表。它包含了所有细节,包括 用户号 uid 进程号 pid 父进程号 ppid 、开始时间、命令,等等。这里所有的进程号你都可以在宿主的进程表里搜索到。这就是我们在第二个命令里做得。这证明了容器确实是宿主系统中的进程。

如何停止 Docker 容器?

只需要 stop 命令!同样,它采用容器名称或 ID 作为参数。

root@kerneltalks # docker container stop cranky_cori
cranky_cori

如何列出停止的或不活动的 Docker 容器?

现在我们停止了我们的容器,这时如果我们使用 ls 命令,它将不会出现在列表中。

root@kerneltalks # docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

所以,在这种情况下,如果想要查看停止的或不活动的容器,你需要在 ls 命令里同时使用 -a 参数。

root@kerneltalks # docker container ls -a
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS                     PORTS               NAMES
c46f2e9e4690        httpd               "httpd-foreground"   33 minutes ago      Exited (0) 2 minutes ago                       cranky_cori

有了 -a 参数,现在我们可以查看已停止的容器。注意这些容器的状态被标注为 已退出 exited 。既然容器只是一个进程,那么用“退出”比“停止”更合适!

如何(重新)启动 Docker 容器?

现在,我们来启动这个已停止的容器。这和运行一个容器有所区别。当你运行一个容器时,你将启动一个全新的容器。当你启动一个容器时,你将开始一个已经停止并保存了当时运行状态的容器。它将以停止时的状态重新开始运行。

root@kerneltalks #  docker container start c46f2e9e4690
c46f2e9e4690

root@kerneltalks # docker container ls -a
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                NAMES
c46f2e9e4690        httpd               "httpd-foreground"   35 minutes ago      Up 8 seconds        0.0.0.0:80->80/tcp   cranky_cori

如何移除 Docker 容器?

我们使用 rm 命令来移除容器。你不可以移除运行中的容器。移除之前需要先停止容器。你可以使用 -f 参数搭配 rm 命令来强制移除容器,但并不推荐这么做。

root@kerneltalks # docker container rm cranky_cori
cranky_cori
root@kerneltalks # docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

你看,一旦移除了容器,即使再使用 ls -a 命令也查看不到容器了。


via: https://kerneltalks.com/virtualization/8-basic-docker-container-management-commands/

作者:Shrikant Lavhate 选题:lujun9972 译者:lonaparte 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出