thekroko / uthgard-herald

Help us build a herald.
GNU General Public License v3.0
13 stars 18 forks source link

Make Docker deployable #9

Closed burfo closed 7 years ago

burfo commented 7 years ago

Make sure everything can be deployed via docker ("docker run .." should produce a local webserver listening on some random port that displays that page).

scrypt-kitty commented 7 years ago

I can help with this - just for local dev purposes, right? Setting up a VM environment to build this - hope to get a chunk of work done on it tomorrow. Feel free to assign this issue to me if possible.

burfo commented 7 years ago

Not just for local dev purposes. They plan to use Docker to deploy the live site as well.

Of course you can use

npm install
ng build

To build the app. Then either ng serve to run the built-in angular web server or take the /dist/ folder (created by ng build) and use with another web server. (Not sure if one option is better than the other.)

scrypt-kitty commented 7 years ago

I'm not sure what the staff want to do, but depending on what their webservers are like the dev version can just be used with a reverse proxy to serve up the live site too. I'm going to build a container and we can adjust accordingly. We can always maintain a prod image if necessary.

jearle commented 7 years ago

@burfo serving static files is going to be a lot faster, and should make the container a lot small (just nginx no node runtime)

scrypt-kitty commented 7 years ago

It would be great if we could setup the asset delivery for nginx instead of node runtime. Node / npm was a nightmare to deploy to a docker image and ng serve isn't staying up. I can try just adding nginx but not sure if ng serve does anything angular / node specific that needs to be configured.

jearle commented 7 years ago

@gp2015 #16

I added an nginx pull request, with a few other additions, that i probably should have made their own pull requests.

jearle commented 7 years ago

@gp2015 so all ng serve does is setup a watcher on your file system via webpack to compile your TS into js along with all your assets (images/templates/styles). It has a bunch of debug information (ie source maps) and very limited optimization of the output code (so you get slower loads).

ng build compiles your assets into optimized bundles of code and throws it in the dist folder which can be statically served (only needs a web browser to run).

burfo commented 7 years ago

Fixed by #16

scrypt-kitty commented 7 years ago

I was actually looking at making this a docker image for build and deployment but this gets the job done for dev.

jearle commented 7 years ago

What's missing for build/deploy?

Dockerfile

FROM nginx

COPY ./nginx/conf.d /etc/nginx/conf.d
COPY ./herald/dist /usr/share/nginx/html

EXPOSE 80

package.json

"docker:build:nginx": "docker build -t uthgard-nginx $(pwd)/.."
scrypt-kitty commented 7 years ago

I meant as an image:

FROM repo/uthgard-herald

You solution is elegant and probably better for this kind of project that doesn't need CI. Nice work!

jearle commented 7 years ago

Well you wouldn't use this as a base image, so FROM wouldn't really be useful within a Dockerfile, but you could definitely tag it to uthgard/herald and push it to docker hub.

ie

https://hub.docker.com/r/jearle/uthgard-nginx/

now you can just run:

docker run -p 8787:80 -d jearle/uthgard-nginx

thekroko commented 7 years ago

No need to push any images to the docker hub; I'm fine building the images myself on the server from git (I'd actually prefer that).

I'd prefer reducing the entire build & run process to a simple Makefile similar to this:

INSTANCE=uth-go-mainpage
IMAGE=uth-mainpage

.PHONY: build
build:
        docker build -t $(IMAGE) .

.PHONY: runlocal
runlocal: build stop
        docker run -it --name $(INSTANCE) $(IMAGE)

.PHONY: run
run: build stop
        docker run --restart on-failure -d --name $(INSTANCE) $(IMAGE)

.PHONY: stop
stop:
        docker stop $(INSTANCE) || /bin/true
        docker rm $(INSTANCE) || /bin/true

Dockerfile:

FROM golang:1.6-alpine

COPY . /go
RUN go install -v main
CMD main

I.e. create a Dockerfile that just copies the current directory content into the docker image, and spins up some lightweight http server to serve the frontend

jearle commented 7 years ago

What does a hand rolled static go server have over nginx?

thekroko commented 7 years ago

I'm not saying to use a go-server (that was just an example Makefile + Dockerimage), but I'm saying to create a makefile that can be build and run docker images from the git repo directly (without the need to go through Dockerhub)

simon-mueller commented 7 years ago

You could switch over from GitHub to GitLab.

GitLab has built-in Container Registry for Continuous Integration (CI), so you don't need dockerhub anymore.

If you cannot setup a GitLab server own your own, I can offer you to use mine (https://git.simon-mueller.de)...

thekroko commented 7 years ago

Given that we have a single-instance webserver, I'd just like to avoid having any kind of image registry all together

jearle commented 7 years ago

@thekroko Yeah, I agree... I wrote something akin to that using npm run if you checkout the package json.

If we wanted to be really uncoupled we should also add a node container that builds the project, leaving the only dependency on the target server docker.

burfo commented 7 years ago

So, here's what we can do right now...

  1. Get the code and build it:

    git clone https://github.com/thekroko/uthgard-herald
    cd uthgard-herald/herald
    npm install
    npm run build
  2. Fire up a Docker container (based on the nginx image) that serves the freshly built dist directory: npm run docker:run:nginx

  3. Build a new Docker image from it: npm run docker:build:nginx

@thekroko is this sufficient or what should we change?

thekroko commented 7 years ago

Would be great if the npm commands are run inside the docker container. I want to avoid installing anything on the server directly besides docker.

I'd probably use this as a base: https://hub.docker.com/_/node/

ghost commented 7 years ago

Is there a specific reason you want your own image to do the building? Should be easier to just use the Node image itself. If the command to build it gets a bit lengthy, just put it in a build.sh script in the repo or something.

Took a quick shot at it and cooked up the following, it breaks on the ng build, but I'm also using the wrong version of angular-cli, aught to fix that later.

docker run  -it --rm --name uthgard-herald-build -v $(pwd)/herald:/usr/src/app -w /usr/src/app node:7.4 sh -c 'npm install && npm install -g angular-cli  && ng build'
thekroko commented 7 years ago

I'd prefer to have the npm install in the image itself so it doesn't have to be done on every server restart, but please base the image upon one of the node alpine images.

You should be using the "RUN" command in the dockerbuild for installing all dependencies. Dockerbuild should look something along those lines:

FROM node:alpine RUN apk update && apk upgrade RUN apk add npm

WORKDIR /uthgard ADD . /uthgard ENTRYPOINT [ "node", "server.js" ]

Look here for a rough overview: https://www.digitalocean.com/community/tutorials/docker-explained-using-dockerfiles-to-automate-building-of-images

jearle commented 7 years ago

@thekroko you should group your run scripts together ie:

RUN apk update && apk upgrade && apk add npm

Every RUN creates a new image snapshot, increasing the disk usage of your docker images. Unless you have a reason to create the intermediary update/upgrade snapshot.

ghost commented 7 years ago

I forgot to do a quick write-up after hacking around during a lunch break some time ago where I, despite my utter lack of knowledge of Angular, got it to build inside Docker. I had to bump dependencies to fix some problems, but that's since been done on master here as well. Besides that, I was also unable to fetch a certain dependency, but having python/make/g++ in the container allows it to build it itself instead.

After a successful build, I spun up a container that runs ng serve, exposing :4200. This results in a happy message that the development server is up and running, but when I actually tried to access it, it came up blank. It didn't complain about anything in the logs, not that I could find, at least. (I may be out of my element here. :sweat_smile:) How do you actually want to run this?

FROM node:7.4-alpine

# Copy in the herald
COPY ./herald /usr/src/app

# Can't pull in some dependency, npm resorts to building it itself, but needs Py/Make/g++
# https://github.com/AngularClass/angular2-webpack-starter/issues/626
RUN apk update && apk upgrade && apk add python make g++

# Build the herald
WORKDIR /usr/src/app
RUN npm install -q && npm build

# Run the herald
CMD npm start
scrypt-kitty commented 7 years ago

I thought this was already working? I can take a look later if it isn't.

jearle commented 7 years ago

i believe the CMD should be npm build, the container shouldn't be used to serve the web app, rather just to build the static assets and served from a fast server (nginx).

ghost commented 7 years ago

That's how I saw it originally, but I had a talk with @thekroko on the IRC and I figured he wanted an image that both builds and serves the website, something about sequential execution of containers being difficult. It's entirely possible that I misunderstood him, though, as I was focus pulling on my necro at the same time.

jearle commented 7 years ago

Well ideally you'd have a build pipeline that would look something like:

git push (kicks off the following commands on a CI server) docker build -t uthgard-herald . docker run -v $(pwd)/dist:/angular/app/dist uthgard-herald cd ./nginx docker build -t uthgard-herald-nginx . (the Dockerfile would COPY from ../dist or you could supply an env var to build)

Now you would have an nginx container with the static built assets, which can be shared and deployed wherever.

andir commented 7 years ago

I implemented this somewhat today (e4b90d8b19e53bc462b90aa7212ee159fc41c982). The Docker image now builds the "app" on image build time. This bloats up the image a bit (thats a downside compared to having a simple docker "container" containing all the assets and running it off a standard webserver) but these days that shouldn't really matter.

I'm happy to invest a bit more time to fix potential issues/implement stuff if needed.

thekroko commented 7 years ago

Deployable now, looks good. Looks like AngularJS is running in debug instead of production mode though in the game.

https://herald.uthgard.org/

burfo commented 7 years ago

Yeah, it's in dev mode rather than prd mode due to how the build script is configured. We'd need to change it to do ng build -prod (instead of ng build), or create a 2nd script if we want build to stay in dev mode.

andir commented 7 years ago

I kinda believe that when you build the docker image (to deploy it somewhere) you always want a production build. If you agree just merge https://github.com/thekroko/uthgard-herald/pull/25 :-)