Docker Dev Environment for GO - docker

What I want to do
I want to set up docker dev environment fo Go.
Code
// directory
project(absolute path: /Uses/[username]/project)
|--- app
| |--- config
| | |___ config.go
| |--- main.go
| |___ config.ini
|--- docker-compose.yml
|___ Dockerfile
// main.go
package main
import (
"app/config"
"fmt"
)
func main() {
fmt.Println("Hello World")
fmt.Println(config.Config.ApiKey)
fmt.Println(config.Config.ApiSecrete)
}
// docker-compose.yml
version: '3.8'
services:
app:
build: .
tty: true
volumes:
- ./app:/go/src/app
// Dockerfile
FROM golang:latest
RUN mkdir /go/src/app
WORKDIR /go/src/app
ENV GO111MODULE=on
ENV GOPATH /go
ADD ./app /go/src/app/
Dev Environment
When I run docker-compose exec app go env, I get
GOPATH="/go"
GOROOT="/usr/local/go"
Problem
When I run docker-compose up -d --build,
I get
package app/config is not in GOROOT (/usr/local/go/src/app/config).
So, I can't import "app/config" in main.go file.
I want to know how import self-made package when I set up GO dev environment with docker.

You can follow the go-env-series about how to use Docker to define your Go development environment in code.
Example: chris-crone/containerized-go-dev
The second article does mention go mod init, which helps with import path:
Let’s make the current directory the root of a module by using go mod init:
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
The go.mod file only appears in the root of the module.
Packages in subdirectories have import paths consisting of the module path plus the path to the subdirectory.
For example, if we created a subdirectory world, we would not need to (nor want to) run go mod init there.
The package would automatically be recognized as part of the example.com/hello module, with import path example.com/hello/world.

Thanks to you, I've solved this problem, so I'll share.
I run go mod init app, and go mod tidy.
Then, I change Dockerfile to set GO111MODULE=on.
version: '3.8'
services:
app:
build: .
tty: true
volumes:
- ./app:/go/src/app
environment:
- "GO111MODULE=on"
// directory
project(absolute path: /Uses/[username]/project)
|--- app
| |--- config
| | |___ config.go
| |--- main.go
| |--- config.ini
| |--- go.mod
| |___ go.sum
|--- docker-compose.yml
|___ Dockerfile
cf.
1
2

Related

Why my docker-compose build is failing when copying files

I have a project that is running just fine using fastAPI (main.py). Now I want to share it as a docker image. Here is what I am doing:
My project has this structure:
project
│ docker-compose.yaml
| requirements.txt
│
└───<dir>services
│
└───<dir>api
| │ Dockerfile
| │ main.py
| |
| <dir>model
| file.model
| file.model
└───<dir>statspy
file.dev.toml
file.prod.toml
My Dockerfile:
FROM python:3.10
RUN pip install fastapi uvicorn transformers
COPY . /api /api/api
ENV PYTHONPATH=/api
WORKDIR /api
EXPOSE 8000
ENTRYPOINT ["uvicorn"]
CMD ["api.main:app", "--host", "0.0.0.0"]
docker_compose.yaml
version: "3"
services:
docker_model:
build: ./services/api
ports:
- 8000:8000
labels:
- "statspy.enable=true"
- "statspy.http.routers.fastapi.rule=Host(`fastapi.localhost`)"
topic_v5:
image: statspy:v5.0
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "$PWD/services/statspy/statspy.dev.toml:/etc/statspy/statpys.toml"
when I run docker-compose build it fails with this error message:
Step 3/8 : COPY ./api /api/api
COPY failed: file not found in build context or excluded by .dockerignore: stat api: file does not exist
What am I doing wrong here?
Your build context in the docker-compose file is build: ./services/api
project
│ docker-compose.yaml
| requirements.txt
│
└───<dir>services
│
└───<dir>api <--- docker_model Dockerfile executes from here
| │ Dockerfile
| │ main.py
| |
| <dir>model
| file.model
| file.model
└───<dir>statspy
file.dev.toml
file.prod.toml
You later try to do COPY ./api /api/api. There is no api dir in /services/api, so the COPY directive fails.
What you probably want to do instead is COPY . /api. The rest of the Dockerfile looks correct.

Why docker-compose and dockerfile working this way? [duplicate]

I created a docker file.
FROM node:13.6.0-alpine3.10
WORKDIR /src
RUN apk add --no-cache bash
COPY ./package.json .
COPY ./package-lock.json .
RUN npm install
COPY . .
EXPOSE 8081
CMD npm run start:dev
Structure of my project.
.
└── my-app
└── docker-compose.yml
└── ...
└── server
└── docker
└── Dockerfile
└── src
└── ....
├── package.json
├── package-lock.json
└── ...
When I build the container, I get an error.
ERROR: Service 'server' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder791989542/package.json: no such file or directory
I understand that my files are in a different directory. I tried to solve my problems like this.
COPY ./../package.json .
COPY ./../package-lock.json .
But I also got an error
ERROR: Service 'server' failed to build: COPY failed: Forbidden path outside the build context: ../package.json ()
How to tell the docker so that he is looking for files not in the docker folder where the dockerfile file is located, but in the src folder, where my package-lock.json and package.json files are located
I created a docker-compose.yml file.
version: "3.3"
services:
server:
container_name: server
command:
- npm
- run
- start:dev
build:
context: ./server/docker
dockerfile: dockerfile
environment:
PORT: 8081
ports:
- 8081:8081
restart: on-failure
volumes:
- ./server:/src/
As explained earlier in comments and previous answers, you cannot copy files which are outside of the build context. So you either need to change the context up the directory path or to move the needed files inside the current context.
Looking at your layout, I would go for the first solution and by default use your base directory as context (once you understand the solution, you can adapt context and dockerfile to fit your exact needs).
In your Dockerfile, change the following lines:
COPY ./server/package.json .
COPY ./server/package-lock.json .
Note: the line COPY . . should be removed (or you need to explain a littke better what you actually try to achieve with this)
The build section in your docker-compose.yml file should become:
build:
context: .
dockerfile: server/docker/Dockerfile
The equivalent manual build would be
cd /path/to/my-app
docker build -f server/docker/Dockerfile .
You cannot do that, because first step of build, is to build the context dirs. You need to change the context.
Straight from docker docs,
COPY obeys the following rules:
The path must be inside the context of the build;
you cannot COPY ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

Module path issue while trying to run Go Echo app in 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

How do I create a Dockerfile that allows me to create two different containers depending on a command line parameter?

I have a project with a current version, let's call it A, and a future version, which we'll call B.
Both go services reside in the same project under .../cmd/A and .../cmd/B.
What I'd like to do is create a docker container for A and another one for B.
I can see here that I can add a FROM ... for each in the Dockerfile but how do I use the docker-composer to generate two separate containers? Ideally, this would be a command line flag or two different docker-composer files. (Or maybe I can have two different Dockerfiles too?)
you can do this with docker entry points the same as it is done below
docker-compose
rubygems-1:
container_name: "ruby-container-1"
image: My-image
command: service-b
rubygems-2:
container_name: "ruby-container-2"
image: My-image
command: service-a
docker file
FROM ruby:2.6.3-alpine
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
docker-entrypoint
#!/bin/sh -e
case $1 in
service-a)
bundle exec puma -C config/puma.rb
;;
service-b)
bundle exec puma -C config/puma2.rb
;;
*)
exec "$#"
;;
esac
exit
Each separate container you declare in your docker-compose.yml file can have a separate build: block. That can declare a separate dockerfile: for each image. In the context of a Go package you'll probably need to always include the entire package in the upload, in particular including the go.mod file in the repository root.
So if your directory layout looks like:
myapp
+-- docker-compose.yml
+-- Dockerfile.A
+-- Dockerfile.B
+-- go.mod
+-- go.sum
\-- cmd
+-- A
| \-- main.go
\-- B
\-- main.go
Then you can point your docker-compose.yml file at both Dockerfiles:
version: '3'
services:
version-a:
build:
context: .
dockerfile: Dockerfile.A
version-b:
build:
context: .
dockerfile: Dockerfile.B
If you have a single Dockerfile that builds and installs both versions of the package, you can also override the command: for each container, matching the Dockerfile CMD directive:
version: '3'
services:
version-a:
build: .
command: A
version-b:
build: .
command: B

Docker does not search for a file in a directory

I created a docker file.
FROM node:13.6.0-alpine3.10
WORKDIR /src
RUN apk add --no-cache bash
COPY ./package.json .
COPY ./package-lock.json .
RUN npm install
COPY . .
EXPOSE 8081
CMD npm run start:dev
Structure of my project.
.
└── my-app
└── docker-compose.yml
└── ...
└── server
└── docker
└── Dockerfile
└── src
└── ....
├── package.json
├── package-lock.json
└── ...
When I build the container, I get an error.
ERROR: Service 'server' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder791989542/package.json: no such file or directory
I understand that my files are in a different directory. I tried to solve my problems like this.
COPY ./../package.json .
COPY ./../package-lock.json .
But I also got an error
ERROR: Service 'server' failed to build: COPY failed: Forbidden path outside the build context: ../package.json ()
How to tell the docker so that he is looking for files not in the docker folder where the dockerfile file is located, but in the src folder, where my package-lock.json and package.json files are located
I created a docker-compose.yml file.
version: "3.3"
services:
server:
container_name: server
command:
- npm
- run
- start:dev
build:
context: ./server/docker
dockerfile: dockerfile
environment:
PORT: 8081
ports:
- 8081:8081
restart: on-failure
volumes:
- ./server:/src/
As explained earlier in comments and previous answers, you cannot copy files which are outside of the build context. So you either need to change the context up the directory path or to move the needed files inside the current context.
Looking at your layout, I would go for the first solution and by default use your base directory as context (once you understand the solution, you can adapt context and dockerfile to fit your exact needs).
In your Dockerfile, change the following lines:
COPY ./server/package.json .
COPY ./server/package-lock.json .
Note: the line COPY . . should be removed (or you need to explain a littke better what you actually try to achieve with this)
The build section in your docker-compose.yml file should become:
build:
context: .
dockerfile: server/docker/Dockerfile
The equivalent manual build would be
cd /path/to/my-app
docker build -f server/docker/Dockerfile .
You cannot do that, because first step of build, is to build the context dirs. You need to change the context.
Straight from docker docs,
COPY obeys the following rules:
The path must be inside the context of the build;
you cannot COPY ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

Resources