Module path issue while trying to run Go Echo app in docker - docker

I am having a weird issue to run a Go Echo Framework. It works fine when I use the docker run command, that is no dependency issue and it executes the file properly but while running docker-compose up it gives error:
Creating echo_app ... done
Attaching to echo_app
echo_app | server.go:6:2: cannot find package "github.com/labstack/echo/v4" in any of:
echo_app | /usr/local/go/src/github.com/labstack/echo/v4 (from $GOROOT)
echo_app | /go/src/github.com/labstack/echo/v4 (from $GOPATH)
echo_app exited with code 1
Below are my files:
Dockerfile
FROM golang:1.15-alpine
LABEL maintainer="Me"
RUN apk update
RUN apk add git
# Setting up Dev environment
RUN mkdir /echo_app
COPY . /echo_app/
WORKDIR /echo_app/
# Download Echo Framework with help of Go mod (Credit: https://github.com/labstack/echo/issues/1374#issuecomment-559990790)
# Init to create Go Module
RUN go mod init app.com/main
# Building to download echo framework and other dependencies
RUN go build
# RUN the server
#CMD go run server.go
EXPOSE 1323
docker-compose.yml
version: "3"
services:
web:
container_name: echo_app
image: echo_app:latest
build: ./
command: go run server.go
volumes:
- .:/echo_app
ports:
- "1323:1323"

FROM golang:1.15-alpine
LABEL maintainer="Me"
# Setting up Dev environment
WORKDIR /echo_app/
# note this file, go.mod exists locally. and contain reference
# to direct/indirect dependencies. this step allows to download
# dependencies and speedup build for docker images (if it used
# to build artifacts, and not as dev env).
COPY go.mod /echo_app/go.mod
RUN go mod download
EXPOSE 1323

Related

How should I dockerize and deploy a NestJS monorepo project?

I have NestJS monorepo project with structure as below:
...
apps
app1
app2
app3
...
If I got an idea correctly, I have possibility to run all the applications in same time, i.e. I run command and have access to apps by paths like http://my.domain/app1/, http://my.domain/app2/, http://my.domain/app3/ or in some similar way. And I need to put all apps in a docker container(s) and run them from there.
I haven't found something about this proceess. Did I undestand the idea correctly and where could I know more about deployment NestJS monorepo project?
This is how I solved it:
apps
app1
Dockerfile
...
app2
Dockerfile
...
app3
Dockerfile
...
docker-compose.yml
Each Dockerfile does the same:
FROM node:16.15.0-alpine3.15 AS development
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:16.15.0-alpine3.15 AS production
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production --omit=dev
COPY --from=development /usr/src/app/dist ./dist
CMD ["npm", "run", "start-app1:prod"]
Where the last line should start the application so adjust that to your project naming.
Later you should build each of the images in your CI/CD pipeline and deploy them separately. To run the docker build from the root folder of the project you just need to provide a Dockerfile path for -f parameter, for example:
docker build -f apps/app1/Dockerfile -t app1:version1 .
docker build -f apps/app2/Dockerfile -t app2:version1 .
docker build -f apps/app3/Dockerfile -t app3:version1 .
To run it locally for tests, utilize docker-compose.yml
version: '3.8'
services:
app1:
image: app1:version1
ports:
- 3000:3000 # set according to your project setup
app2:
...
app3:
...
And start it by calling docker compose up

Docker error can't copy a file after build it

I'm trying to copy my ./dist after building my angular app.
here is my Dockerfile
# Create image based off of the official Node 10 image
FROM node:12-alpine
RUN apk update && apk add --no-cache make git
RUN mkdir -p /home/project/frontend
# Change directory so that our commands run inside this new directory
WORKDIR /home/project/frontend
# Copy dependency definitions
COPY package*.json ./
RUN npm cache verify
## installing packages
RUN npm install
COPY ./ ./
RUN npm run build --output-path=./dist
COPY /dist /var/www/front
but when I run docker-compose build dashboard I get this error
Service 'dashboard' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builderxxx/dist: no such file or directory
I don't know why is there something wrong?
if you need to check also docker-compose file
...
dashboard:
container_name: dashboard
build: ./frontend
image: dashboard
container_name: dashboard
restart: unless-stopped
networks:
- app-network
...
The Dockerfile COPY directive copies content from the build context (the host-system directory in the build: line) into the image. If you're just trying to move around content within the image, you can RUN cp or RUN mv to use the ordinary Linux shell commands instead.
RUN npm run build --output-path=./dist \
&& cp -a dist /var/www/front

"No Go files in..." error when i use go with docker compose

I installed Go on Ubuntu 16.04. This is my GOPATH=/home/{username}/work.
I created a project into /home/{username}/work/src.
This is my project folder hierarchy.
project-name
services
configuration
api
main.go
Dockerfile
bff
api
main.go
Dockerfile
docker-compose.yml
favicon.ico
README.md
I can build and run with my dockerfile but I can't build and up with docker-compose.
I couldn't find any solution.
Configuration service dockerfile:
FROM golang:1.11.1-alpine3.8 as builder
RUN apk update && apk add git && go get gopkg.in/natefinch/lumberjack.v2
RUN mkdir -p /go/src/project-name/services/configuration
RUN CGO_ENABLED=0
RUN GOOS=linux
ADD . /go/src/project-name/services/configuration
ENV GOPATH /go
WORKDIR /go/src/project-name/services/configuration/api
RUN go get
RUN go build
FROM alpine
RUN apk update
RUN apk add curl
RUN mkdir -p /app
COPY --from=builder /go/src/project-name/services/configuration/api/ /app/
RUN chmod +x /app/api
WORKDIR /app
EXPOSE 5001
ENTRYPOINT ["/app/api"]
It works with dockerfile.
This is my docker-compose file:
version: '3.4'
services:
bff:
image: project-name/bff:${TAG:-latest}
build:
context: .
dockerfile: services/bff/Dockerfile
ports:
- "5000:5000"
container_name: bff
depends_on:
- configuration
configuration:
image: project-name/configuration:${TAG:-latest}
build:
context: .
dockerfile: services/configuration/Dockerfile
ports:
- "5001:5001"
container_name: configuration
It didn't work.
When the “run go get” command runs, it gives an error, the error is:
can't load package: package project-name/services/configuration/api: no Go files in /go/src/project-name/services/configuration/api
ERROR: Service 'configuration' failed to build: The command '/bin/sh -c go get' returned a non-zero code: 1
In your Dockerfile, you say
ADD . /go/src/project-name/services/configuration
which expects the build context directory on the host to contain the source files. But your docker-compose.yml file says
build:
context: .
dockerfile: services/configuration/Dockerfile
where the context directory is the root of your source control tree, not the specific Go source directory you're trying to build. If you change this to
build:
context: services/configuration
# Default value of "dockerfile: Dockerfile" will be right
it will likely work better.
In plain Docker commands, your current docker-compose.yml file says the equivalent of
cd $GOPATH/src/project-name
docker build -f services/configuration/Dockerfile .
But you're probably actually running
cd $GOPATH/src/project-name/services/configuration
docker build .
and what directory is the current directory matters.

Keep Docker intermediate layers in multistage build

I'm attempting to have a dev container and a "production" container built from a single Dockerfile, it already "works" but I do not have access to the dev container after the build (multistage intermediaries are cached, but not tagged in a useful way).
The Dockerfile is as-so:
# See https://github.com/facebook/flow/issues/3649 why here
# is a separate one for a flow using image ... :(
FROM node:8.9.4-slim AS graphql-dev
WORKDIR /graphql-api
ENV PATH /graphql-api/node_modules/.bin:$PATH
RUN apt update && apt install -y libelf1
ADD ./.babelrc /graphql-api/
ADD ./.eslintignore /graphql-api/
ADD ./.eslintrc /graphql-api/
ADD ./.flowconfig /graphql-api/
ADD ./.npmrc /graphql-api/
ADD ./*.json5 /graphql-api/
ADD ./lib/ /graphql-api/lib
ADD ./package.json /graphql-api/
ADD ./schema/ /graphql-api/schema
ADD ./yarn.lock /graphql-api/
RUN yarn install --production --silent && npm install --silent
CMD ["npm", "run", "lint-flow-test"]
# Cleans node_modules etc, see github.com/tj/node-prune
# this container contains no node, etc (golang:latest)
FROM golang:latest AS graphql-cleaner
WORKDIR /graphql-api
ENV PATH /graphql-api/node_modules/.bin:$PATH
COPY --from=graphql-dev graphql-api .
RUN go get github.com/tj/node-prune/cmd/node-prune
RUN node-prune
# Minimal end-container (Alpine 💖)
FROM node:8.9.4-alpine
WORKDIR /graphql-api
ENV PATH /graphql-api/node_modules/.bin:$PATH
COPY --from=graphql-cleaner graphql-api .
EXPOSE 3000
CMD ["npm", "start"]
Ideally I'd be able to start graphql-dev and the final container both with a docker-compose.yml, as so:
version: '3'
services:
graphql-dev:
image: graphql-dev
build: ./Dockerfile
volumes:
- ./lib:/graphql-api/lib
- ./schema:/graphql-api/schema
graphql-prod:
image: graphql
build: ./Dockerfile
The two final steps are the "shrinking" for the final build (saves over 250Mb for us) are not really required except for in the production build.
If I extract the dockerfile into two.. somehow Dockerfile.prod and Dockerfile.dev then I have to manage dependencies between them as I can't force prod to always build dev (can I?)
If I were somehow able to specify target on the build in the docker-compose.yml file I could do it, there were some issues, but specifying a target under build in my yml file yields an error:
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.graphql-dev.build contains unsupported option: 'target'

Use Docker to run a build process

I'm using docker and docker-compose to set up a build pipeline. I've got a front-end that's written in javascript and needs to be built before being used. The backend is written in go.
To make this component integrate with the rest of our docker-compose setup, I want to do the building in a docker image as well.
This is the flow I'm going for:
during build do:
build the frontend stuff and put it in /output (that is bound to the
output volume
build the backend server
when running do:
run the server, it has access to the build files in /output
I'm quite new to docker and docker-compose so I'm not sure if this is possible, or even the right thing to do.
For reference, here's my docker-compose.yml:
version: '2'
volumes:
output:
driver: local
services:
frontend:
build: .
volumes:
- output:/output
backend:
build: ./backend
depends_on:
- frontend
volumes:
- output:/output
and Dockerfile:
FROM node
# create working dir
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ADD package.json /usr/src/app/package.json
# install packages
RUN npm install
COPY . /usr/src/app
# build frontend files and place results in /output
RUN npm build
RUN cp /usr/src/app/build/* /output
And backend/Dockerfile:
FROM go
# copy and build server
COPY . /usr/src/backend
WORKDIR /usr/src/backend
RUN go build
# run the server
ENTRYPOINT ["/usr/src/backend/main"]
Something is wrong here, but I do not know what. It seems as though the output of the build step are not persisted in the output volume. What can I do to fix this?
You cannot attach a volume during docker build.
The reason for this is that the goal of the docker build command is to build an image, and nothing else, it doesn't need to have volumes, as Dockerfile has ADD / COPY.
To produce your output, you should create a script which mostly does the npm install ; npm build ; cp /usr/src/app/build/* /output from your current dockerfile and use this script as the entrypoint / cmd in your dockerfile.
I'm not sure compose can run this, but in any case, I find it more clear wrapped in a shell script that first executes the frontend builder container, then executing the backend container with the output directory as a volume.

Resources