String.ToLower().mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine as a base.String.ToLower().Uppercase cyrillic characters should become lowercase after a call to String.ToLower().
Uppercase cyrillic characters remain uppercase after a call to String.ToLower().
Works fine in the Debian-based mcr.microsoft.com/dotnet/core/aspnet:3.0 image.
See the attached project for repro:
Initial string: 袩袪袠袙袝孝 PRIVET. Container output when running docker-compose up:
to-lower-test-alpine_1 | 袩袪袠袙袝孝 privet
to-lower-test-debian_1 | 锌褉懈胁械褌 privet
docker versionDocker version 19.03.2, build 6a30dfc
docker infoClient:
Debug Mode: false
Server:
Containers: 13
Running: 2
Paused: 0
Stopped: 11
Images: 106
Server Version: 19.03.2
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc version: 425e105d5a03fabd737a126ad93d62a9eeede87f
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 4.9.184-linuxkit
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.952GiB
Name: docker-desktop
ID: HXTF:N7FS:QCDZ:VLFL:HX7O:4JZJ:XFZG:7ZYN:6YIF:WAK3:3SON:HQXU
Docker Root Dir: /var/lib/docker
Debug Mode: true
File Descriptors: 40
Goroutines: 58
System Time: 2019-10-01T19:38:33.2742731Z
EventsListeners: 2
HTTP Proxy: gateway.docker.internal:3128
HTTPS Proxy: gateway.docker.internal:3129
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
Sounds like you are running into the globalization invariant mode:
String casing (ToUpper and ToLower) will be performed for the ASCII range only. Requests to case code points outside that range will not be performed, however no exception will be thrown. In other words, casing will only be performed for character range ['a'..'z'].
The original alpine announcement talks about invariant mode too:
We have been considering various design decisions to make .NET Core Alpine base images as small as possible to align with that. In this first iteration, we enabled .NET Core 2.0 Globalization Invariant Mode in order to reduce the default size of the image. This change reduced the image by ~30MB.
https://github.com/dotnet/dotnet-docker/issues/986#issuecomment-472467432 describes how to disable it. I think the short version is to do this in your own dockerfile:
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
RUN apk add --no-cache icu-libs
Here's a complete dockerfile that shows how to enable full globalization mode: https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/Dockerfile.alpine-x64-globalization
Thanks @omajid, that seems to do the job:
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
RUN apk add --no-cache icu-libs
Is it okay though that this behavior changed from 2.2-alpine to 3.0-alpine?
Oh, sorry, I didn't use globalization related code prior to 3.0-alpine, so I guess it has always been this way (since 2.0-alpine).
Mystery solved.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
RUN apk add --no-cache icu-libs
gives on build
Sending build context to Docker daemon 45.19MB
Step 1/3 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine
---> 3628001d3a2c
Step 2/3 : ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
---> Running in a8edbaffd678
Removing intermediate container a8edbaffd678
---> 2cf2c20a4f95
Step 3/3 : RUN apk add --no-cache icu-libs
---> Running in df2135d80a3f
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz: No such file or directory
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz: No such file or directory
ERROR: unsatisfiable constraints:
icu-libs (missing):
required by: world[icu-libs]
The command '/bin/sh -c apk add --no-cache icu-libs' returned a non-zero code: 1
@SquallHalle Did you solve your issue? I get the same error when using the aspnetcore 2.2-alpine images:
mcr.microsoft.com/dotnet/core/aspnet:2.2-alpine
mcr.microsoft.com/dotnet/core/aspnet:2.2-alpine3.9
Most helpful comment
Sounds like you are running into the globalization invariant mode:
The original alpine announcement talks about invariant mode too:
https://github.com/dotnet/dotnet-docker/issues/986#issuecomment-472467432 describes how to disable it. I think the short version is to do this in your own dockerfile: