+ All Categories
Home > Documents > Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm...

Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm...

Date post: 26-Jun-2020
Category:
Upload: others
View: 5 times
Download: 0 times
Share this document with a friend
88
@giltayar Docker and the Path to a Better Staging Environment Gil Tayar (@giltayar) March 2019 This presentation: http://bit.ly/docker-and-the-path-devopspro https://github.com/giltayar/docker-and-the-path 1
Transcript
Page 1: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Docker and the Path to a Better Staging Environment

Gil Tayar (@giltayar)March 2019This presentation: http://bit.ly/docker-and-the-path-devopsprohttps://github.com/giltayar/docker-and-the-path

1

Page 2: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar@giltayar

About Me ● My developer experience goes all the way back to the ‘80s.

● Am, was, and always will be a developer● Testing the code I write is my passion● Currently evangelist and architect @

Applitools● We deliver Visual Testing tools:

If you’re serious about testing, checkout Applitools Eyes

● Sometimes my arms bend back● But the gum I like is coming back in style

@giltayar

2

Page 3: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Staging Environments

3

Page 4: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Staging Environments● The environment where the application is deployed to,

prior to deployment in production● Also used prior to integrating code between teams● Usually one environment, but can be more● And, unfortunately…

4

Page 5: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Almost, but not quite, entirely unlike production

(apologies to Douglas Adams)

5

Page 6: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Staging Environments● Built using a combination of chewing gum and baling wire● Not maintained as well as the production environment● Not the same deployment procedure● Not the same production infrastructure

6

Page 7: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

And this is where we test...

7

Page 8: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

8

Page 9: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Revolution!

9

Page 10: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Revolution in...● How apps are developed● How apps are tested● How apps are deployed to production

10

Page 11: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

This Talk

● What Docker is● How to use it with Docker-compose● How to use it with Kubernetes● How to build a production and staging

environment with it

11

Page 12: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Put your seatbelt on, it’s going to be a wild

and technical ride

12

Page 13: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

End Goal● Run our application in a staging environment using

Docker● Simple application:

○ MongoDB database○ Blogging web application (frontend and backend)

13

Page 14: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

How would we run Mongo in a staging environment?● Install it on one of the machines in Staging

or…

● Build a VM image that includes Mongodb, and run it on AWS, Azure, VMware…

14

Page 15: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Problematic● Installing:

○ Automated install scripts are not easy

● VM image:○ We can run two!○ Not easy building the image○ Every version, the VM needs to be rebuilt○ Start time is minutes.○ But it’s the better option.

15

Page 16: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Virtual Hardware

The VM Option

Blog app

VM1

mongodb

VM2

Operating System Operating System

Hypervisor (AWS, Vmware, Hyper-V…)

Virtual Hardware

Hardware

16

Page 17: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

The Docker Option

Blog app

Docker Container 1

mongodb

Process Isolation Process Isolation

Operating System

Hardware

Docker Container 2

17

Page 18: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Let’s Run MongoDB under Docker

18

Page 19: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

DockerfileFROM ubuntu

WORKDIR /data

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -y

RUN apt-get install -q -y mongodb

RUN mkdir -p /data/db

EXPOSE 27017

CMD ["mongod"]

● An image is a frozen container● A template for docker containers● Set of instructions that is run in

the container:● Runs the base image (FROM)● Executes the RUN-s

(using WORKDIR and ENV)● Adds some metadata to container

(CMD, EXPOSE)● Freezes the result into a docker

image

19

Page 20: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Building the docker image

docker build . -t mymongo

Where the files areTag the image with a

name

20

Page 21: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running a container

$ docker run mymongo

The image to run

21

Page 22: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Yay! It’s working

MongoDB

Process Isolation

Operating System

Hardware

Docker Container 1

22

27017

Page 23: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Connecting to mongo via mongo client

$ mongo

23

Page 24: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Why isn’t it connecting? (Docker and TCP Ports)

MongoDB

Process Isolation

27017 Mongo

Client

27017

Operating System

Hardware

Docker Container 1

24

Page 25: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running a container with port mappingdocker run -d -p 27017:27017 mymongo

Host Port

Container Port

Detached

25

Page 26: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

This is what port mapping looks like

MongoDB

Process Isolation

27017 Mongo

Client

Operating System

Hardware

Docker Container 1

27017

26

Page 27: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Connecting with Mongo Client$ mongo

> db.users.save({username: 'giltayar', name: 'Gil Tayar'})

> db.users.find()

{ "_id" : ObjectId("5abf3d2bdef8a36d505d3732"), "a" : 1 }

27

Page 28: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

And… it’s connecting!

MongoDB

Process Isolation

27017 Mongo

Client

Operating System

Hardware

Docker Container 1

27017

28

Page 29: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Connecting with Mongo Client$ mongo

> db.users.save({username: 'giltayar', name: 'Gil Tayar'})

> db.users.find()

{ "_id" : ObjectId("5abf3d2bdef8a36d505d3732"), "a" : 1 }

29

Page 30: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running another Mongo container$ docker run -d -p 7017:27017 mymongo

$ mongo localhost:7017

> db.users.save({username: 'giltayar', name: 'Gil Tayar'})

> db.users.find()

{ "_id" : ObjectId("5abf3d2bdef8a36d505d3732"), "a" : 1 }

Use a different host

port

30

Page 31: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Two containers, different host ports

MongoDB

Process Isolation

27017

Mongo

Client

Docker Container 1

27017

MongoDB

Process Isolation

27017

Docker Container 2

7017

31

Page 32: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Maintenance of Docker Containers$ docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS

6e33d46a915c mymongo "mongod" Less than a second ago Up 1 second 0.0.0.0:27017->27017/tcp

44ce252702e6 mymongo "mongod" 9 seconds ago Up 11 seconds 0.0.0.0:7017->27017/tcp

$ docker rm 6e33d46a915c

$ docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS

44ce252702e6 mymongo "mongod" 9 seconds ago Up 11 seconds 0.0.0.0:7017->27017/tcp

32

Page 33: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Let’s Run The Blog App

33

Page 34: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running the Blog App Locally$ cd ../blog-app-example

$ npm install

$ npm run build:frontend

$ npm run dev

34

Page 35: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running the Blog App

MongoDB

Process Isolation

27017 Blog App

Operating System

Hardware

Docker Container 1

27017

3000

35

Page 36: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

DockerfileFROM node

WORKDIR app

ENV NODE_ENV=production

COPY . .

RUN npm install --production

EXPOSE 3000

CMD ["node", "src/app.js"]

● “node” is an image that already has NodeJS installed○ Thousands of these pre-built

images in hub.docker.com.● COPY copies from host directory into

docker directory

36

Page 37: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Building the Blog App

$ cd ../blog-app-example

$ npm run build:frontend

$ docker build . -t myblog

37

Page 38: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

$ docker run -t -p 3000:3000 giltayar/blog-app-example

...

Error: secret should be set

at module.exports (.../index.js:21:42)

at Object.<anonymous> (/app/src/routes/auth.js:14:13)

Running the App38

Page 39: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Twelve Factor Apps● A set of rules on how to run modern web apps● Apply extremely well to docker apps● Rule #3: Store config in the environment● The blog app is a 12-factor app● We have to pass:

○ A SECRET environment variable○ a MONGODB_URI environment variable

For more information: https://12factor.net

39

Page 40: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

$ docker run -t -p 3000:3000 \

-e SECRET=shhhh \

-e MONGODB_URI=localhost:27017 \

giltayar/blog-app-example

...

Error: connect ECONNREFUSED 127.0.0.1:27017

at Object._errnoException (util.js:1003:13)

Running the App

Environment variable

So I can Ctrl+C

40

Page 41: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

localhost in a container refers to the container itself

MongoDB

Process Isolation

27017

Docker Container 1

27017

Blog App

Process Isolation

3000

Docker Container 2

3000

41

Page 42: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

MongoDB

Process Isolation

27017

mymongo

Blog App

Process Isolation

3000

Docker Container 2

3000

What if we could create one network?42

Page 43: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running the App in a network$ docker network create mynet

$ docker run -d \

--network=mynet \

--name=mongo \

mymongo

$ docker run -t -p 3000:3000 \

-e SECRET=shhhh -e MONGODB_URI=mongo:27017 \

--network=mynet \

myblog

Join the network

Use this name

43

Page 44: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running the same app twice$ docker network create mynet

$ docker run -d --network=mynet --name=mongo mymongo

$ docker run -d -p 3000:3000 --network=mynet \

-e SECRET=shhhh -e MONGODB_URI=mongo:27017 myblog

$ docker network create mynet2

$ docker run -d --network=mynet2 --name=mongo2 mymongo

$ docker run -d -p 3001:3000 --network=mynet2 \

-e SECRET=shhhh -e MONGODB_URI=mongo2:27017 myblog

44

Page 45: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Let’s try them...http://localhost:3000

http://localhost:3001

45

Page 46: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

MongoDB

Process Isolation

mymongo

Blog App

Process Isolation

3000

Docker Container 2

3000

MongoDB

Process Isolation

mymongo

Blog App

Process Isolation

3000

Docker Container 2

3001

46

Page 47: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

What if there was an even simpler way to run multiple containers?

47

Page 48: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Docker Compose!

48

Page 49: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Docker Compose● Write a file (docker-compose.yml)● The file declares all the containers and the connections between them● Then just “run” the docker composition

Let’s do it!

49

Page 50: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

docker-compose.ymlversion: '3'

services:

mongo:

image: mymongo

blog:

image: myblog

environment:

SECRET: shhh

MONGODB_URI: mongo:27017

ports:

- "3000:3000"

50

Page 51: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Running it

$ docker-compose up

or…

$ docker-compose up -d

51

Page 52: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Trying ithttp://localhost:3000

52

Page 53: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

$ docker-compose stop

or…

$ docker-compose down

Killing it53

Page 54: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Can we run two instances of a docker-compose?● Yes, but we need to take care not to use the same host port.● Time, alas, does not permit me to show you the details● You can check the git repo for the full information

54

Page 55: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

OK, this is cool.But what has this got to do with Staging?

55

Page 56: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

docker-compose

● Enables you to run the whole application locally● Does not run your application in a staging

environment… ● … or in production

56

Page 57: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

So whadda we do?

57

Page 58: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

58

Page 59: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

59

Page 60: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Kubernetes is docker-compose for production

60

Page 61: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Kubernetes● Like Docker-compose:

○ Also uses docker containers to run services○ Can also deploy easily using a set of declarative files○ Easy to use

● But better:○ Can deploy multiple services to multiple computers○ Self-heals itself○ Robust enough to be used in production

61

Page 63: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Minikube (or… it might as well have been in the cloud)

Minikube VM

This laptop

63

Page 64: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

apiVersion: apps/v1

kind: Deployment

metadata:

name: myblog

spec:

selector:

matchLabels:

app: myblog

replicas: 1

template:

metadata:

labels:

app: myblog

myblog-1.ymlspec:

containers:

- name: myblog

image: myblog

ports:

- containerPort: 3000

env:

- name: MONGODB_URI

value: 'mymongo:27017'

- name: SECRET

value: 'shhhhhh'

64

Page 65: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Let’s “apply” the yml to the Kubernetes cluster$ kubectl apply -f myblog-1.yml

deployment "myblog" created

$ kubectl get pods

NAME READY STATUS RESTARTS AGE

myblog-56589c8f7f-xdlgz 0/1 ErrImagePull 0 5s

65

Page 66: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Why the “ErrImagePull” Error?

Minikube VM

This laptop

mymongo

myblog

Local docker registry

ubuntu

node

...

Global docker registry

@hub.docker.com

66

Page 67: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Why the “ErrImagePull” Error?

Minikube VM

This laptop

mymongo

myblog

Local docker registry

ubuntu

node

giltayar/mymongo

giltayar/myblog

...

Global docker registry

@hub.docker.com

67

Page 68: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

So let’s push our images to the global docker registry

$ docker tag myblog giltayar/myblog

$ docker push giltayar/myblog

$ docker tag mymongo giltayar/mymongo

$ docker push giltayar/mymongo

68

Page 69: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

apiVersion: apps/v1

kind: Deployment

metadata:

name: myblog

spec:

selector:

matchLabels:

app: myblog

replicas: 1

template:

metadata:

labels:

app: myblog

myblog-2.yml (fixed)spec:

containers:

- name: myblog

image: giltayar/myblog

ports:

- containerPort: 3000

env:

- name: MONGODB_URI

value: 'mymongo:27017'

- name: SECRET

value: 'shhhhhh'

69

Page 70: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Let’s reapply...$ kubectl apply -f myblog-2.yml

$ kc get pods

NAME READY STATUS RESTARTS AGE

myblog-6b4567d975-h89g6 0/1 CrashLoopBackOff 3 3m

$ kc logs myblog-6b4567d975-h89g6

...

Error: getaddrinfo ENOTFOUND mymongo mymongo:27017

70

Page 71: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

apiVersion: apps/v1

kind: Deployment

metadata:

name: mymongo

spec:

selector:

matchLabels:

app: mymongo

replicas: 1

template:

metadata:

labels:

app: mymongo

mymongo.ymlspec:

containers:

- name: mymongo

image: giltayar/mymongo

ports:

- containerPort: 27017

71

Page 72: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Let’s apply the mongo yml$ kubectl apply -f mymongo.yml

$ kc get pods

NAME READY STATUS RESTARTS AGE

myblog-6b4567d975-h89g6 0/1 Error 6 7m

mymongo-67b9bd8c7f-87j2j 1/1 Running 0 2m

$ kc logs myblog-6b4567d975-h89g6

...

Error: getaddrinfo ENOTFOUND mymongo mymongo:27017

72

Page 73: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Same Problem. Why?● Because in docker-compose,

the name of the service is also the way to discover it● In kubernetes, a deployment is just a set of containers.

○ Not discoverable

● To “discover” pods, create a Kubernetes Service

73

Page 74: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Pods are not discoverable

mymongo

myblog

myblog

myblog

K8s Cluster

74

Page 75: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

We need a service

mymongo

myblog

myblog

myblog

mym

ongo-s

erv

ice

K8s Cluster

75

Page 76: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

mymongo-service.ymlkind: Service

apiVersion: v1

metadata:

name: mymongo-service

spec:

selector:

app: mymongo

ports:

- protocol: TCP

targetPort: 27017

port: 27017

76

Page 77: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

apiVersion: apps/v1

kind: Deployment

metadata:

name: myblog

spec:

selector:

matchLabels:

app: myblog

replicas: 1

template:

metadata:

labels:

app: myblog

myblog.yml (fixed again)spec:

containers:

- name: myblog

image: giltayar/myblog

ports:

- containerPort: 3000

env:

- name: MONGODB_URI

value:

'mymongo-service:27017'

- name: SECRET

value: 'shhhhhh'

77

Page 78: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

And now applying...$ kubectl apply -f mymongo-service.yml

service "mymongo-service" created

$ kubectl apply -f myblog.yml

deployment "myblog" configured

$ kc get pods

NAME READY STATUS RESTARTS AGE

myblog-566ccc499c-sx8cf 1/1 Running 0 2m

mymongo-67b9bd8c7f-87j2j 1/1 Running 0 14m

78

Page 79: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Blog is running. Can we access it?

● No! It’s just a set of containers.● We need a service.● But this time, the service needs to be

accessible from outside the cluster!

79

Page 80: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

We need a service

mymongo

myblog

myblog

myblog

mym

ongo-s

erv

ice

K8s Cluster

myblog-service

80

Page 81: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

kind: Service

apiVersion: v1

metadata:

name: myblog-service

spec:

selector:

app: myblog

ports:

- protocol: TCP

targetPort: 3000

port: 3000

type: NodePort # this is how you enable access from outside

myblog-service.yml81

Page 82: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

And now applying...$ kubectl apply -f myblog.yml

service "myblog-service" created

$ kubectl apply -f myblog.yml

deployment "myblog" configured

$ kubectl get services

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)

myblog-service NodePort 10.109.42.144 <none> 3000:31489/TCP

mymongo-service ClusterIP 10.103.150.100 <none> 27017/TCP

82

Page 83: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

And now we try it...$ minikube ip

192.168.64.8

http://192.168.64.8:31489/

83

Page 84: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

And it works!● And the same deployment procedure will work in production...

84

Page 85: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

$ kubectl create namespace blog1

$ kubectl -n blog1 apply -f \

mymongo.yml,\

Mymongo-service.yml,\

myblog.yml,\

myblog-service.yml

Let’s create another parallel environment85

Page 86: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Summary● The long journey…● Running individual containers using docker● Running environments locally using docker-compose● Running environments in a production environment

using Kubernetes

86

Page 87: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

This is how you build your staging environment:

● Docker images built by developers… ● … and deployed into Kubernetes clusters

87

Page 88: Docker and the Path to a Better Staging Environment · ENV NODE_ENV=production COPY . . RUN npm install --production EXPOSE 3000 CMD ["node", "src/app.js"] “node” is an image

@giltayar

Thank You!@giltayarThis presentation: http://bit.ly/docker-and-the-path-starcanadaGithub repo: https://github.com/giltayar/docker-and-the-path

88


Recommended