In this post, I’ll explain how to build a container using buildah
and upload
that into the private registry. We can set the default registry in the crio’s
config file, but this method is not good because some images doesn’t matched
for the arm64 environment system even if that had been provided from quay or
docker.io. So that reason, we keep the blank default registry settings.
- How to Setup the NFS on Ubuntu
- Build the Private Registry with the NFS Volume
- How to Build Container with Buildah
Install buildah
Different from Docker, the running tools and build tools is divided into the
crictl
and the buildah
, so we need to install the buildah
. That package
is provided from the project atomic repository, already installed for the crio,
simply run following command.
sudo apt install -y buildah;
Even if you installed buildah
successfully, some Dockerfile script can’t
build a container image. For example, some Dockerfile script should run
package install command like dnf or apt for the pre-built libraries.
However if you ran that Dockerfile script, buildah
try to search and
run the runc
, but can’t find that in the default PATH environment and
will be failed. The runc
is the core engine to run container in the CRI-O,
so buildah
should use that to run some commands in Dockerfile while building
the custom images. Following Dockerfile is that example file. If you run
this Dockerfile without runc, you can see the following error logs.
FROM docker.io/fedora:latest
MAINTAINER Sungup Moon
RUN dnf install cmake make clang;
$ buildah build-using-dockerfile .
STEP 1: FROM docker.io/fedora:latest
Getting image source signatures
Copying blob 5da54debb5a9 done
Copying config d0b2459d46 done
Writing manifest to image destination
Storing signatures
STEP 2: MAINTAINER Sungup Moon
STEP 3: RUN dnf install cmake make clang;
error running container: error creating container for [/bin/sh -c dnf install cmake make clang;]: : exec: "runc": executable file not found in $PATH
error building at STEP "RUN dnf install cmake make clang;": error while running runtime: exit status 1
ERRO[0095] exit status 1
To reference the runc
, you need to run following command. Fortunately, the
runc had been installed at /usr/lib/cri-o-runc/sbin/runc
when you installed
CRI-O, so you can make link that file into /usr/local/bin
simply.
sudo ln -s /usr/lib/cri-o-runc/sbin/runc /usr/local/bin/runc;
However, if you don’t have a RUN
section in your Dockerfile for the custom
image, you can skip this making link step! :-)
Make example using buildah
Now, we build an example container image to test building and pushing container
into our private registry. In this post, we make a very very simple web page
using nginx image. Make a new directory and make index.html
and
Dockerfile
with following contents.
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
</body>
</html>
FROM docker.io/nginx:alpine
MAINTAINER Sungup Moon
COPY index.html /usr/share/nginx/html
After making two files, run following commands to build and push our image.
The buildah
can run in any user account, so you don’t need to run with
sudo
to get root privileges.
buildah build-using-dockerfile -t {registry address}/hello .;
buildah push {registry address}/hello;
You can check the container images using following command. Also, you can remove images already uploaded from the local registry.
$ buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
{registry address}/hello2 latest 6c30e001557f 2 minutes ago 24.1 MB
docker.io/library/nginx alpine c2efcb34277e 2 days ago 24.1 MB
$ buildah rmi {registry address}/hello2 docker.io/library/nginx:alpine
untagged: {registry address}/hello2:latest
6c30e001557fdb7b812d514026e4d8cc3ccb5c7365071c179e5534c13c4b9a67
untagged: docker.io/library/nginx:alpine
c2efcb34277e5f88b5775b976153d5e1b6be87499e2b1f4e30110db5aab48ef4
Start example service with the new container
Now we start service with the new image. Make the deploy and service YAML file and apply that.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-example
labels:
app: hello-world-example
spec:
replicas: 1
selector:
matchLabels:
app: hello-world-example
template:
metadata:
labels:
app: hello-world-example
spec:
containers:
- name: hello-world-example
image: {registry address}/hello:latest
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-example
labels:
app: hello-world-example
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: hello-world-example
type: ClusterIP
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: hello-world-example
spec:
rules:
- host: "{example domain name}"
http:
paths:
- path: /
backend:
serviceName: hello-world-example
servicePort: 80
kubectl apply -f example-service.yaml;
You can check the example service working fine using curl
command like this:
$ curl -D- http://{example domain name}
HTTP/1.1 200 OK
Server: openresty/1.15.8.2
Date: Sun, 19 Jan 2020 04:41:18 GMT
Content-Type: text/html
Content-Length: 133
Connection: keep-alive
Last-Modified: Sun, 19 Jan 2020 02:34:50 GMT
ETag: "5e23c04a-85"
Accept-Ranges: bytes
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
</body>
</html>