Tải bản đầy đủ - 0 (trang)
Example – Node.js/Express container image

Example – Node.js/Express container image

Tải bản đầy đủ - 0trang

FROM alpine

# load any public updates from Alpine packages

RUN apk update

# upgrade any existing packages that have been updated

RUN apk upgrade

# add/install python3 and related libraries

# https://pkgs.alpinelinux.org/package/edge/main/x86/python3

RUN apk add nodejs nodejs-npm

# make a directory for our application

WORKDIR /src

# move requirements file into the container

COPY package.json .

COPY package-lock.json .

# install the library dependencies for this application

RUN npm install --production

# copy in the rest of our local source

COPY . .

# set the debug environment variable

ENV DEBUG=kfd-nodejs:*

CMD ["npm", "start"]



Like the Python example, this container is based on Alpine Linux.

You will see several commands that may not be familiar,

specifically the apk command. As a reminder, this command is used

to install, update, and remove Alpine Linux packages. These

commands update the Alpine package repository, upgrade all

installed and pre-existing packages in the image, and then install

nodejs and npm from packages. Those steps basically bring us to a

minimal container that can run a Node.js application.

The next commands make a directory in the container at /src to

house our source code, copy in the package.json file, and then use npm

to install the dependencies for running the code. The --production

option used with the npm install command installs only those items

listed in package.json that are needed for running the code development dependencies are excluded. Node.js makes it easy and

consistent to maintain your dependencies with its package.json

format, and it is good practice to separate out dependencies needed

in production from those needed in development.

The last two commands leverage ENV and CMD. This differs from the

Python example where I used CMD and ENTRYPOINT to highlight how they

work together. In this example, I use the ENV command to set the

DEBUG environment variable to match the example instructions in the

Express documentation. CMD then contains a command to start our

code, which simply leverages npm to run the command defined in

package.json, and uses the earlier WORKDIR command to set the local



directory for that invocation.



Building the container

We use the same docker



build



command to create the container:



docker build .



You should see output that looks something like the following:

Sending build context to Docker daemon

Step 1/11 : FROM alpine

---> 76da55c8019d

Step 2/11 : RUN apk update

---> Using cache

---> b44cd5d0ecaa



197.6kB



As you saw with the Python-based example, every step in the

Dockerfile is reflected with output showing you what happened as

Docker was building the container image based on your

instructions (the Dockerfile):

Step 9/11 : COPY . .

---> 6851a9088ce3

Removing intermediate container 9fa9b8b9d463

Step 10/11 : ENV DEBUG kfd-nodejs:*

---> Running in 663a2cd5f31f

---> 30c3b45c4023

Removing intermediate container 663a2cd5f31f

Step 11/11 : CMD npm start

---> Running in 52cf9638d065

---> 35d03a9d90e6

Removing intermediate container 52cf9638d065

Successfully built 35d03a9d90e6



As with the Python example, this builds a container with only an

ID. This example also leverages Quay for hosting the images

publicly, so we will take the image appropriately so we can upload

it to Quay:

docker tag 35d03a9d90e6 quay.io/kubernetes-for-developers/nodejs



As with the Python example, the tag contains three relevant parts quay.io is the container registry. The second ( kubernetes-for-developers) is



the namespace for your containers, and the third (nodejs) is the

name of the container. The same commands as the Python example

are used to upload the container, referencing nodejs instead of flask:

docker login quay.io

docker push quay.io/kubernetes-for-developers/nodejs



The push refers to a repository [quay.io/kubernetes-for-developers/nodejs]

0b6165258982: Pushed

8f16769fa1d0: Pushed

3b43ed4da811: Pushed

9e4ead6d58f7: Pushed

d56b3cb786f1: Pushedfad7fd538fb6: Pushing [==================>

5fbd4bb748e7: Pushing [==================================>

]



2.411MB/3.532MB



0d2acef20dc1: Pushing [==================================================>]

5bef08742407: Pushing [================>

]



1.107MB

1.287MB/3.966MB



]



11



And when it is complete, you should see something akin to the

following:

The push refers to a repository [quay.io/kubernetes-for-developers/nodejs]

0b6165258982: Pushed

8f16769fa1d0: Pushed

3b43ed4da811: Pushed

9e4ead6d58f7: Pushed

d56b3cb786f1: Pushed

fad7fd538fb6: Pushed

5fbd4bb748e7: Pushed

0d2acef20dc1: Pushed

5bef08742407: Pushed

latest: digest: sha256:0e50e86d27a4b29b5b10853d631d8fc91bed9a37b44b111111dcd4fd9f4bc723 size: 6791



Like the Python example, you may want to build and tag in the

same command. For the Node.js example, that command would be:

docker build -t quay.io/kubernetes-for-developers/nodejs:0.2.0 .



This, if run immediately after you built the image, should display

output that looks like the following:



Sending build context to Docker daemon 197.6kB

Step 1/11 : FROM alpine

---> 76da55c8019d

Step 2/11 : RUN apk update

---> Using cache

---> b44cd5d0ecaa

Step 3/11 : RUN apk upgrade

---> Using cache

---> 0b1caea1a24d

Step 4/11 : RUN apk add nodejs nodejs-npm

---> Using cache

---> 193d3570516a

Step 5/11 : WORKDIR /src

---> Using cache

---> 3a5d78afa1be

Step 6/11 : COPY package.json .

---> Using cache

---> 29724b2bd1b9

Step 7/11 : COPY package-lock.json .

---> Using cache

---> ddbcb9af6ffc

Step 8/11 : RUN npm install --production

---> Using cache

---> 1556a20af49a

Step 9/11 : COPY . .

---> Using cache

---> 6851a9088ce3

Step 10/11 : ENV DEBUG kfd-nodejs:*

---> Using cache

---> 30c3b45c4023

Step 11/11 : CMD npm start

---> Using cache

---> 35d03a9d90e6

Successfully built 35d03a9d90e6

Successfully tagged quay.io/kubernetes-for-developers/nodejs:latest



Again, it will be significantly faster as it was using Docker's cache

of the image layers that were previously built.

If you run the docker



images



command, you should now see it listed:



REPOSITORY

quay.io/kubernetes-for-developers/nodejs



TAG

0.2.0



IMAGE ID

46403c409d1f



CREATED

4 minutes ago



If you are pushing your own images to quay.io as a container repository, you

may need to log in to the website and make the images public in addition to

these commands. By default, quay.io will keep images private, even the public

ones, until you approve their exposure on their website.



SIZE

81.9MB



Running your container

Now, let's run the container we just made. We will use the kubectl

command as with the Python example, but replacing flask with

nodejs to specify the container we just made and uploaded:



run



kubectl run nodejs --image=quay.io/kubernetes-for-developers/nodejs:0.2.0 --port=3000

deployment “nodejs” created



To see what it's doing, we need to ask the cluster for the current

state of the resources we just created:

kubectl get deployments

NAME

DESIRED

CURRENT

UP-TO-DATE

AVAILABLE

nodejs

1

1

1

1

kubectl get pods

NAME

READY

STATUS

RESTARTS

nodejs-568183341-2bw5v

1/1

Running

0



AGE

1d

AGE

1d



The kubectl run command works regardless of the language, and in

the same fashion as the Python example. The simple deployment

created in this case is named nodejs, and we can request the same

kinds of information about it that we did with the Python example

earlier:

kubectl get deployment nodejs -o json



The JSON output should will be fairly extensive, and will have

multiple sections. At the top of the output will be apiVersion, kind, and

metadata about the deployment:



{

"apiVersion": "extensions/v1beta1",

"kind": "Deployment",

"metadata": {

"annotations": {

"deployment.kubernetes.io/revision": "1"

},

"creationTimestamp": "2017-09-16T10:06:30Z",

"generation": 1,

"labels": {

"run": "nodejs"

},

"name": "nodejs",

"namespace": "default",

"resourceVersion": "88886",

"selfLink": "/apis/extensions/v1beta1/namespaces/default/deployments/nodejs",

"uid": "b5d94f83-9ac6-11e7-884c-0aef48c812e4"

},



Typically, underneath that will be spec, which has a lot of the core of

what you're just asked to be run:



"spec": {

"replicas": 1,

"selector": {

"matchLabels": {

"run": "nodejs"

}

},

"strategy": {

"rollingUpdate": {

"maxSurge": 1,

"maxUnavailable": 1

},

"type": "RollingUpdate"

},

"template": {

"metadata": {

"creationTimestamp": null,

"labels": {

"run": "nodejs"

}

},

"spec": {

"containers": [

{

"image": "quay.io/kubernetes-for-developers/nodejs:0.2.0",

"imagePullPolicy": "IfNotPresent",

"name": "nodejs",

"ports": [

{

"containerPort": 3000,

"protocol": "TCP"

}

],

"resources": {},

"terminationMessagePath": "/dev/termination-log",

"terminationMessagePolicy": "File"

}

],

"dnsPolicy": "ClusterFirst",

"restartPolicy": "Always",

"schedulerName": "default-scheduler",

"securityContext": {},

"terminationGracePeriodSeconds": 30

}

}

},



And the final section is status, which indicates the current state (as

of the request for this information) of the deployment:



"status": {

"availableReplicas": 1,

"conditions": [

{

"lastTransitionTime": "2017-09-16T10:06:30Z",

"lastUpdateTime": "2017-09-16T10:06:30Z",

"message": "Deployment has minimum availability.",

"reason": "MinimumReplicasAvailable",

"status": "True",

"type": "Available"

}

],

"observedGeneration": 1,

"readyReplicas": 1,

"replicas": 1,

"updatedReplicas": 1

}

}



When a Pod runs in Kubernetes, it is running in a sandbox, isolated

from the rest of the world. Kubernetes does this intentionally, so

you can specify what systems can communicate with each other,

and what can be accessed from outside. For most clusters, the

defaults for Kubernetes allow any Pod to communicate with any

other Pod. Just like the Python example, you can leverage one of

two commands with kubectl to get direct access from your

development machine: kubectl port-forward or kubectl proxy.



Port forwarding

Now we can use that name to ask kubectl to set up a proxy that will

forward all traffic from a local port we specify to a port associated

with the Pod we determine. The Node.js example runs on a

different port than the Python example (port 3000 instead of port

5000), so the command needs to be updated accordingly:

kubectl port-forward nodejs-568183341-2bw5v 3000:3000



The output should be something like the following:

Forwarding from 127.0.0.1:3000 -> 3000

Forwarding from [::1]:3000 -> 3000



This is forwarding any and all traffic that gets created on your local

machine at TCP port 3000 to TCP port 3000 on the nodejs-5681833412bw5v Pod.

Just as with the Python example, you don't get a Command Prompt

back yet because the command is actively running to keep this

particular tunnel alive. As a reminder, you can cancel or quit the

kubectl command by pressing Ctrl + C and port forwarding will

immediately end.

While the command is still running, open a browser and put in this

URL: http://localhost:3000. The response should come back that says,

Index Page. When we invoked the kubectl run command, I specifically

choose port 3000 to match the default from Express.



Proxy

Since this is an HTTP-based application, we can also use the kubectl

proxy command to get access to the responses from our code:

kubectl proxy



And the output will show something akin to the following:

Starting to serve on 127.0.0.1:8001



As a reminder, you won't get a prompt back in the Terminal

window until the proxy terminates. Just as with the Python

example, we can determine the URL to use that the proxy will use

to forward to our container based on the Pod name and the

namespace that we used when invoking the kubectl run command.

Since we did not specify a namespace, it used the default, which is

called default. The URL pattern for accessing the Pod is the same as

the Python example:

http://localhost:8001/api/v1/proxy/namespaces//pods//



And in the case of our Pod, this would be:

http://localhost:8001/api/v1/proxy/namespaces/default/pods/nodejs-568183341-2bw5v/



If you open a URL in your browser created with the Pod name that

your Kubernetes cluster assigned, it should show you the same

output that you saw using the port-forward command.



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Example – Node.js/Express container image

Tải bản đầy đủ ngay(0 tr)

×